我在MSVC 12和GCC 4.8上遇到嵌套模板类的问题。我已将其缩小为以下代码段:
#include <vector>
#include <list>
template <typename A, typename B>
struct Base
{
template <typename A2, typename B2> struct InBase { };
};
template <typename A, typename B>
struct Derived : public Base<A, B>
{
typedef Base<A, B> MyBase;
// this works on GCC 4.8
typedef typename MyBase::template InBase<A, B> MyInBase;
// this works on MSVC 12
typedef MyBase::InBase<A, B> MyInBase;
typedef std::vector<MyInBase*> MyInBaseVector;
typedef std::list<MyInBase*> MyInBaseList;
MyInBaseList list;
};
当我在GCC上使用MyInBase
的MSVC变体时,它只是告诉我添加typename
和template
,我觉得这是可以理解的。当我在MSVC上使用GCC变体时(我认为它是正确的),它会报告:
deptypes.cpp(20) : error C2955: 'Base<A,B>::InBase' : use of class template requires template argument list
deptypes.cpp(7) : see declaration of 'Base<A,B>::InBase'
deptypes.cpp(24) : see reference to class template instantiation 'Derived<A,B>' being compiled
C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\INCLUDE\vector(648) : error C2955: 'Base<A,B>::InBase' : use of class template requires template argument list
deptypes.cpp(7) : see declaration of 'Base<A,B>::InBase'
deptypes.cpp(7) : see declaration of 'Base<A,B>::InBase'
deptypes.cpp(21) : error C2955: 'Base<A,B>::InBase' : use of class template requires template argument list
deptypes.cpp(7) : see declaration of 'Base<A,B>::InBase'
C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\INCLUDE\list(859) : error C2955: 'Base<A,B>::InBase' : use of class template requires template argument list
deptypes.cpp(7) : see declaration of 'Base<A,B>::InBase'
deptypes.cpp(7) : see declaration of 'Base<A,B>::InBase'
MSVC错误是否正确?如果是,我该如何解决?
答案 0 :(得分:3)
MSVC在这里拒绝有效代码,因为N3337 14.2(temp.names)p4状态:
当成员模板专精的名称出现在
.
或->
之后 postfix-expression 或在 qualified-id 中的嵌套名称说明符之后,以及 postfix-expression 的对象表达式取决于类型或 qualified-id 中的 nested-name-specifier 是指依赖类型,但名称 不是当前实例化的成员(14.6.2.1),成员模板名称必须 以关键字template
为前缀。否则,假定名称命名为a 非模板。
鉴于此,我在Godbolt上针对ICC 13和Clang 3.3检查了您的样本:ICC在接受符合性nontype "Base<A, B>::InBase [with A=A, B=B]" is not a template
/ {{1}时正确拒绝此{{}}} MSVC主义有趣的是,Clang同时接受符合和的不一致的typedef!我的MSVC 11(VS2012)的本地副本也拒绝其中包含typename
和template
的版本,以及传递模板参数列表,如错误所示(在任何情况下都是格式错误)
似乎template
关键字也是MSVC的绊倒,这阻止了GCC 4.9建议使用其他冗余typename
来强制表达式为依赖关系上下文而不使用template
。
Visual Studio开发人员已经aware of a very similar issue to this。至于解决它呢?您只需使用Derived::MyBase::template InBase<A, B>
块来保存typedef的MSVC特定版本。
对于学生来说:ICC,尽管它在世界某些角落被扯掉, 在实践中符合C ++标准,因为它使用与Comeau C ++相同的EDG前端。