My problem can be resumed by the following piece of code:
template <typename T> struct C2;
template <typename T>
struct C1
{
template <typename Type,
template <typename Ti> class Container = C2>
void m() {}
};
template <typename T>
struct C2
{
template <typename Type = int,
template <typename Ti> class Container = C2> // <-- Here is the problem!
void m() {}
};
The gnu compiler, version 4.8.1 fails with the following message:
test-temp.C:16:47: error: invalid use of type ‘C2<T>’ as a default value for a template template-parameter
template <typename Ti> class Container = C2>
It refers to default template parameter C2 for the the method C2::m.
Apparently (it is my opinion), the compiler is seeing C2<T>
as default parameter instead of C2
(without <T>
). So, when it finds the instruction it fails because type C2<T>
does not match with Container
.
However, clang++, just for exactly the same code, compiles fine!
My questions:
Thanks in advance
Leandro
If one template parameter has a default argument, then all template parameters following it must also have default arguments. For example, the compiler will not allow the following: template<class T = char, class U, class V = int> class X { };
A template parameter is a special kind of parameter that can be used to pass a type as argument: just like regular function parameters can be used to pass values to a function, template parameters allow to pass also types to a function.
Function Template is the correct terminology (a template to instantiate functions from). Template Function is a colloquial synonym. So, there's no difference whatsoever.
Like function default arguments, templates can also have default arguments.
There is no semantic difference between class and typename in a template-parameter. typename however is possible in another context when using templates - to hint at the compiler that you are referring to a dependent type. §14.6.
I think Clang is correct, and g++ is in error, quote from the draft Standard (bold emphasis is mine)
14.6.1 Locally declared names [temp.local]
1 Like normal (non-template) classes, class templates have an injected-class-name (Clause 9). The injectedclass-name can be used as a template-name or a type-name. When it is used with a template-argument-list, as a template-argument for a template template-parameter, or as the final identifier in the elaborated-typespecifier of a friend class template declaration, it refers to the class template itself. Otherwise, it is equivalent to the template-name followed by the template-parameters of the class template enclosed in <>.
You can use the ::
scope resolution operator to beat g++ into submission
template <typename T>
struct C2
{
template <typename Type = int,
template <typename Ti> class Container = ::C2>
// ^^ <-- here is the solution!
void m() {}
};
Live Example.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With