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
Copy Constructor Is Not Inherited
Multi-Threading Benchmarking Issues
Should I Return Exit_Success or 0 from Main()
Qgraphicsview Zooming in and Out Under Mouse Position Using Mouse Wheel
How to Scale Down Numbers from Rand()
Why Is Std::Unordered_Map Slow, and How to Use It More Effectively to Alleviate That
How to Set a Default Argument from a Previous Argument
Argument of Type "Char *" Is Incompatible with Parameter of Type "Lpwstr"
Conversion from String Literal to Char* Is Deprecated
How to Delete a Non-New Object
Issue When Scheduling Tasks Using Clock() Function
How to Identify Platform/Compiler from Preprocessor MACros
Nested Templates with Dependent Scope
Fast Cross-Platform C/C++ Image Processing Libraries