MSVC:STL容器中的“使用类模板需要模板参数列表”

时间:2014-09-25 11:18:56

标签: c++ templates visual-c++ gcc stl

我在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变体时,它只是告诉我添加typenametemplate,我觉得这是可以理解的。当我在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错误是否正确?如果是,我该如何解决?

1 个答案:

答案 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)的本地副本也拒绝其中包含typenametemplate的版本,以及传递模板参数列表,如错误所示(在任何情况下都是格式错误)

似乎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前端。