I'm porting my c++ windows code (msvc & intel) to Linux (g++). The code uses lots of templates (I like metaprogramming ;-). But I can't compile this code:
template <class TA>
struct A
{
template <class TAB> struct B;
};
template <class TC>
struct C {};
template <class TD>
struct D
{
template <class TTD> class T {};
};
template<class TA>
template<class TBA>
struct A<TA>::B : C<typename D<TA>::T<TBA> >
{
int foo;
};
g++ tells me that in definition of A::B, C class has invalid template arguments. But on msvc and intel it works well! What's the problem here? PS: Sorry, I can't post the original code, because it's too template-complicated. But this example is virtually the same and gives the same error on g++. Thank you.
UPDATE: I've found the problem is in TBA argument of T. g++ doensn't like usage of second template in the definition.
You need the template
keyword
template<class TA>
template<class TBA>
struct A<TA>::B : C<typename D<TA>::template T<TBA> >
{
int foo;
};
GCC is correct to give a diagnostic here. This is because T
cannot be looked up in the dependent scope D<TA>
. The meaning of the <
after it depends on whether T
is a template or not. The Standard says that T
shall be assumed to be not a template and thus T
cannot be followed by a template argument list.
template
is like typename
in that it tells the compiler to treat T
as a template and that the <
is the start of an argument list in any case. The Standard says in paragraphs 14.2/2
and 14.2/4
For a template-name to be explicitly qualified by the template arguments, the name must be known to refer to a template.
When the name of a member template specialization appears after . or -> in a postfix-expression, or after nested-name-specifier in a qualified-id, and the postfix-expression or qualified-id explicitly depends on a template-parameter (14.6.2), the member template name must be prefixed by the keyword template. Otherwise the name is assumed to name a non-template.
In your case, you have T
appear after the nested-name-specifier D<TA>
which depends on the template-parameter TA
. For the typename-specifier to parse correctly, the construct D<TA>::T<TBA>
must interpret T
as the name of a class template, which 14.2
forbids.
On that topic, it's always a good idea to try and compile with Clang
main1.cpp:21:37: error: use 'template' keyword to treat 'T' as a dependent template name
struct A<TA>::B : C<typename D<TA>::T<TBA> >
^
template
1 error generated.
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