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