Compiler bug: error : nontype "<...>" is not a template

Compiler bug: error : nontype "<...>" is not a template

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

8 posts / 0 new
Last post
For more complete information about compiler optimizations, see our Optimization Notice.

 

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

http://publib.boulder.ibm.com/infocenter/lnxpcomp/v8v101/index.jsp?topic=%2Fcom.ibm.xlcpp8l.doc%2Flanguage%2Fref%2Fkeyword_typename.htm

http://publib.boulder.ibm.com/infocenter/lnxpcomp/v8v101/index.jsp?topic=%2Fcom.ibm.xlcpp8l.doc%2Flanguage%2Fref%2Fkeyword_typename.htm

Judy

 

 

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

 

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

 

I see those errors with 13.1 but not with 14.0. 13.1 is no longer being updated.

 

Judy

 

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

 

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

That's fine, I have already redesigned my code to work around this problem.

Good to know that it's already fixed though!

Manuel

 

Login to leave a comment.