我将我的c ++ windows代码(msvc& intel)移植到Linux(g ++)。代码使用了很多模板(我喜欢元编程;-)。但是我无法编译这段代码:
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 ++告诉我,在A :: B的定义中,C类具有无效的模板参数。但是在msvc和intel上运行良好!这有什么问题? PS:对不起,我无法发布原始代码,因为它太模板复杂了。但是这个例子实际上是相同的,并且在g ++上给出了相同的错误。 谢谢。
更新:我发现问题出现在T. g ++的TBA参数中,并不喜欢在定义中使用第二个模板。
答案 0 :(得分:10)
您需要template
关键字
template<class TA>
template<class TBA>
struct A<TA>::B : C<typename D<TA>::template T<TBA> >
{
int foo;
};
GCC在这里给出诊断是正确的。这是因为无法在依赖范围T
中查找D<TA>
。 <
之后的含义取决于T
是否为模板。标准说T
应该假定不是模板,因此T
不能跟随模板参数列表。
template
与typename
类似,它告诉编译器将T
视为模板,<
在任何情况下都是参数列表的开头。标准在段落14.2/2
和14.2/4
对于要由模板参数显式限定的模板名称,必须知道名称才能引用 到模板。
当成员模板专业化的名称出现之后。或 - &gt;在postfix-expression中,或者在qualified-id中的nested-name-specifier之后,postfix-expression或qualified-id显式依赖于template-parameter(14.6.2),成员模板名称必须以关键字模板。否则,假定该名称命名非模板。
在您的情况下,T
出现在嵌套名称说明符D<TA>
之后,取决于模板参数TA
。要使typename-specifier正确解析,构造D<TA>::T<TBA>
必须将T
解释为类模板的名称,14.2
禁止。{1}}。
关于该主题,尝试使用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.