Template Within Template: Why "'>>' Should Be '> >' Within a Nested Template Argument List"

Template within template: why ` ' should be ` ' within a nested template argument list

Sometimes you want it to be >>. Consider

boost::array<int, 1024>>2> x;

In C++03 this successfully parses and creates an array of size 256.

Need help understanding the meaning of within a nested template argument list error given by GCC

Stuff between outer pair of brackets (1) is a template argument list for std::map template

std::map<int, std::vector<int>>
// (1) ^ ^
// (2) ^ ^

The inner pair (2) is template argument list for std::vector template and it's nested inside the first and that's what the error is saying.

Prior to C++11, a whitespace was mandatory between >> at the end to make life easier for the parser (as you observed, it would be interpreted as right shift operator instead). Many compilers made the effort to parse it correctly anyway, in order to give a meaningful error message, proving that's not impossible. I guess that's one of the reasons this restriction was relaxed in C++11.

Error in nested template argument when compile c++ in unix

Pre-C++11, nested template arguments had to have a space between the two closing angle brackets:

map<string, vector<string> >
// here^

C++11 allows you to omit that space. If you're stuck with C++03, just make sure you follow that particular syntax rule.

Why is gcc 4.8.1 giving me the should be within a nested templated list error? Wasn't this fixed in C++11?

Are you compiling this correctly?

try this:

g++ -std=c++11 -o program program.cpp

C++ nested template issue

This is an interesting case! My position whether it is a compiler or standard problem is similar to @lubgr, but I wanted to add some more insights.

ICC also have some problems with your construct, which might suggest that this is more deeply rooted in standard (still, gcc might be correct here). It fails with error: "template argument list must match the parameter list" - this might mean that for both compilers this:

template<typename FOO>
template<typename Foo<FOO>::Value VALUE>

are not identical with original definition of Foo. It seems to be a bug of both compilers, but I've learned to be cautious when two different compilers share similar problems.

Extracting definition of Value from original template to separate one fixes the case (code on Compiler Explorer):

template<typename T>
struct X
{
using Value = int;
};

template<typename FOO>
struct Foo
{
template<typename X<FOO>::Value VALUE>
struct Bar;
};

template<typename FOO>
template<typename X<FOO>::Value VALUE>
struct Foo<FOO>::Bar { static void test(); };

template<typename FOO>
template<typename X<FOO>::Value VALUE>
void Foo<FOO>::Bar<VALUE>::test() {}

int main() { return 0; }

You can fix this as well by simply using hardcoded Value type (code on Compiler Explorer) - but this is not what you need probably:

template<typename FOO>
struct Foo
{
template<int VALUE>
struct Bar;
};

template<typename FOO>
template<int VALUE>
struct Foo<FOO>::Bar { static void test(); };

template<typename FOO>
template<int VALUE>
void Foo<FOO>::Bar<VALUE>::test() {}

int main() { return 0; }

Hope it helps!

How do nested templates get resolved in C++?

You have to take in count that there are three types of template parameters:

1) types

2) non-types (or values)

3) template-templates

The first type is preceded by typename (or class)

template <typename T>
void foo (T const & t);

In the preceding example, T is a type and t (a classical function argument) is a value of type T.

The second type of template parameter are values and are preceded by the type of the value (or auto, starting from C++17, for a not specified type)

template <int I>
void bar ()
{ std::cout << I << std::endl; }

In the preceding example the I template parameter is a value of type int.

The third type is the most complex to explain.

Do you know (I suppose) that std::vector<int> and std::vector<double> are different types, but they have in common std::vector, a template class.

A template-template parameter is a parameter that accept std::vector, the template class without arguments.

A template-template parameter is preceded by a template keyword, as in the following example

template <template <int> class C>
void baz ();

The template-template parameter C in the preceding example is class (or struct) that require a single int (value) template parameter.

So if you have a class

template <int I>
class getInt
{ };

you can pass getInt, as template parameter, to baz()

baz<getInt>();

Now you should be able to understand your code:

template <class T, template <class...> class Template>
struct is_specialization : std::false_type {};

the is_specialization struct is a template struct that receive, as template parameters, a type (T) and a template-template Template that accept classes/structs receiving a variadic number of type template parameters.

Now you have a specialization of is_specialization:

template <template <class...> class Template, class... Args>
struct is_specialization<Template<Args...>, Template> : std::true_type {};

This specialization is selected when the first template parameter (Template<Args...>) is a class based on the second (Template).

An example: if you instantiate

is_specialization<std::vector<int>, std::map>

the main version (that inherit from std::false_type) is selected because std::vector<int> isn't based on std::map.

But if you instantiate

is_specialization<std::vector<int>, std::vector>

the specialization (that inherit from std::true_type) is selected because std::vector<int> is based on std::vector.

Nested class-template argument deduction with parentheses: GCC vs. clang

Comments to this question state that this is a GCC bug. It has been filed as GCC bug report 89062.

How to avoid clang-format to format two separate ' ' into a shift?

There is the Standard option that you can use. You want the C++03 option (which would include C++98), as that would format double > in templates to include a white space in between them.

Standard: Cpp03

You can even use Auto instead so that clang-format can auto detect the C++ version used.

Visual C++: Using nested templates, is it possible to mark instead of as error?

C++11 made >> to end nested templates legal. The issue is that VC++ 2010 implements (and enables unconditionally) this part of C++11, but you're using other compilers which either don't implement this in the version you're targeting or you haven't enabled their C++11 mode.

VC++ doesn't support modes and instead simply enables bits and pieces of language specs as they get around to implementing them. So your solution is to either downgrade the VC++ compiler to a version that doesn't enable this feature, or upgrade or enable C++11 on the other compilers you're targeting so that this is not an error.


If you can't do either of those, and if you're not already using an automated build system then you can set one up to help catch these compatibilities errors faster than you currently are. Configure one so that as soon as any team member commits new code the code is checked on all the platforms you support.

Automated build systems often also allow users to provide code changes to be checked on all the build slaves directly from the team member's working directory, instead of requiring the code to be committed to the shared repo first. Setting this up is just about as good as having the initial development occur directly on each supported platform.



Related Topics



Leave a reply



Submit