- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Actually both declarations are incorrect (and will not compile with Microsoft or g++). On Windows (for compatibility with Microsoft) we allow "implicit typename" and "implicit template" in some situations but if you really want to fix your code to be standard compliant you need to change these declarations to:
// this works
template <class T>
TestStruct<typename Types::template Append<T> > add() {
return TestStruct<typename Types::template Append<T> >(); }
// this doesn't
template <class... T>
TestStruct<typename Types::template Append<T...> > add() { return TestStruct<typename Types::template Append<T...> >(); }
Some relevant links:
http://eigen.tuxfamily.org/dox/TopicTemplateKeyword.html
Judy
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
You are right. I figured that typename is necessary since Types is a dependet name, but it didn't work because I forgot that I also have to use the additional template keyword. I ended up trying different variations with and without typename.
However, the new (now hopefully standard compliant) code still doesn't compile:
template <class... Types> struct TypeList { template <class... AppendTypes> using Append = TypeList<Types..., AppendTypes...>; }; template <class Types> struct TestStruct { template <class... T> TestStruct<typename Types::template Append<T...>> add() { return TestStruct<typename Types::template Append<T...>>(); } }; int main() { TestStruct<TypeList<>> foo; auto x = foo.add<int, float>().add<char>(); }
Error:
1>ConsoleTests.cpp(21): 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 21 1> 1>ConsoleTests.cpp(21): error : type name is not allowed 1> auto x = foo.add<int, float>().add<char>(); 1> ^ 1> 1>ConsoleTests.cpp(21): error : expected an expression 1> auto x = foo.add<int, float>().add<char>();
Best regards,
Manuel Pöter
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
What version of the compiler are you using? What platform? Are you using any special switches?
This compiles for me using the latest 14.0 update:
!% cat play.cpp
extern "C" int printf(const char*,...);
template <class... Types>
struct TypeList
{
template <class... AppendTypes>
using Append = TypeList<Types..., AppendTypes...>;
};
template <class Types>
struct TestStruct
{
// this works
template <class T>
TestStruct<typename Types::template Append<T> > add() {
printf("in here\n");
return TestStruct<typename Types::template Append<T> >(); }
// this doesn't
template <class... T>
TestStruct<typename Types::template Append<T...> > add() { printf("in here 2\n
"); return TestStruct<typename Types::template Append<T...> >(); }
};
int main()
{
TestStruct<TypeList<> > foo;
auto x = foo.add<int, float>().add<char>();
}
!% icl -c /Qstd=c++11 play.cpp
Intel(R) C++ Compiler XE for applications running on IA-32, Version 14.0 Beta Bu
ild x
Built Feb 19 2014 11:40:00 by jward4 on JWARD4-DESK in D:/workspaces/14_0cfe/dev
Copyright (C) 1985-2014 Intel Corporation. All rights reserved.
play.cpp
!%
Judy
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I see those errors with 13.1 but not with 14.0. 13.1 is no longer being updated.
Judy
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I am using Visual Studio 2013 and Intel C++ Compiler XE 14.0.2.176. I don't use any special switches, this is a standard console application with default settings generated by Visual Studio.
I can also reproduce the error compiling on the command line using the same arguments that you posted.
Manuel
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I tried our archived 14.0 compilers and it looks like this problem was fixed on 03/04/14 -- I can reproduce it on compiler earlier than this date but not after. I think this was the date that a long standing problem with template aliases (DPD200242895) was checked in. So I'm sorry but it looks like you will have to wait for the next 14.0 update to get the fix for this one. That will be 14.0 update 3.
Judy
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
That's fine, I have already redesigned my code to work around this problem.
Good to know that it's already fixed though!
Manuel

- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page