Мне кажется, проблема в том, что шаблон функции переменной считается только объявленным после того, как вы указали тип возвращаемого значения, так что sum
в decltype
никогда не сможет ссылаться на сам шаблон функции переменной. Но я не уверен, что это ошибка GCC или C ++ 0x просто не позволяет этого. Мое предположение состоит в том, что C ++ 0x не допускает "рекурсивный" вызов в части ->decltype(expr)
.
В качестве обходного пути мы можем избежать этого «рекурсивного» вызова в ->decltype(expr)
с помощью пользовательского класса черт:
#include <iostream>
#include <type_traits>
using namespace std;
template<class T> typename std::add_rvalue_reference<T>::type val();
template<class T> struct id{typedef T type;};
template<class T, class... P> struct sum_type;
template<class T> struct sum_type<T> : id<T> {};
template<class T, class U, class... P> struct sum_type<T,U,P...>
: sum_type< decltype( val<const T&>() + val<const U&>() ), P... > {};
Таким образом, мы можем заменить decltype
в вашей программе на typename sum_type<T,P...>::type
, и она будет скомпилирована.
Редактировать: Так как это на самом деле возвращает decltype((a+b)+c)
вместо decltype(a+(b+c))
, что было бы ближе к тому, как вы используете сложение, вы можете заменить последнюю специализацию на эту:
template<class T, class U, class... P> struct sum_type<T,U,P...>
: id<decltype(
val<T>()
+ val<typename sum_type<U,P...>::type>()
)>{};