This code:
template <class... Types> struct TypeList { template <class... AppendTypes> using Append = TypeList<Types..., AppendTypes...>; }; template <class Types> struct TestStruct { // this works template <class T> TestStruct<Types::Append<T>> add() { return TestStruct<Types::Append<T>>(); } // this doesn't template <class... T> TestStruct<Types::Append<T...>> add() { return TestStruct<Types::Append<T...>>(); } }; int main() { TestStruct<TypeList<>> foo; auto x = foo.add<int, float>().add<char>(); }
produces the following error:
1>ConsoleTests.cpp(17): error : nontype "Types::Append" is not a template 1> TestStruct<Types::Append<T...>> add() { return TestStruct<Types::Append<T...>>(); } 1> ^ 1> 1>ConsoleTests.cpp(23): error : template instantiation resulted in unexpected function type of "TestStruct<TypeList<int, float>> ()" (the meaning of a name may have changed since the template declaration -- the type of the template is "TestStruct<TypeList<T>> ()") 1> auto x = foo.add<int, float>().add<char>(); 1> ^ 1> detected during instantiation of "TestStruct<Types>::add [with Types=TypeList<>]" based on template arguments <int, float> at line 23 1> 1>ConsoleTests.cpp(23): error : type name is not allowed 1> auto x = foo.add<int, float>().add<char>(); 1> ^ 1> 1>ConsoleTests.cpp(23): error : expected an expression 1> auto x = foo.add<int, float>().add<char>();
I've tried the following workaround:
template <class... Types> struct TypeList { template <class... AppendTypes> using Append = TypeList<Types..., AppendTypes...>; }; template <class TypeList, class... Types> struct AppendHelper; template <class... TypeListTypes, class... Types> struct AppendHelper<TypeList<TypeListTypes...>, Types...> { using TypeList = TypeList<TypeListTypes..., Types...>; }; template <class TypeList, class... Types> using Append = typename AppendHelper<TypeList, Types...>::TypeList; template <class Types> struct TestStruct { template <class... T> TestStruct<Append<Types, T...>> add() { return TestStruct<Append<Types, T...>>(); } }; int main() { TestStruct<TypeList<>> foo; auto x = foo.add<int, float>().add<char>(); }
this fixes the first error, but the others remain:
1>ConsoleTests.cpp(30): error : template instantiation resulted in unexpected function type of "TestStruct<Append<TypeList<>, int, float>> ()" (the meaning of a name may have changed since the template declaration -- the type of the template is "TestStruct<AppendHelper<TypeList<>, T>::TypeList> ()") 1> auto x = foo.add<int, float>().add<char>(); 1> ^ 1> detected during instantiation of "TestStruct<Types>::add [with Types=TypeList<>]" based on template arguments <int, float> at line 30 1> 1>ConsoleTests.cpp(30): error : type name is not allowed 1> auto x = foo.add<int, float>().add<char>(); 1> ^ 1> 1>ConsoleTests.cpp(30): error : expected an expression 1> auto x = foo.add<int, float>().add<char>();
In my opinion both versions are legal C++11 code.
Best regards,
Manuel Pöter