【问题标题】:MSVC: "use of class template requires template argument list" inside STL containersMSVC:“使用类模板需要模板参数列表”在 STL 容器中
【发布时间】:2014-09-25 11:18:56
【问题描述】:

我对 MSVC 12 和 GCC 4.8 上的嵌套模板类有疑问。我已将其简化为以下 sn-p:

#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 错误是否正确?如果是,我该如何解决?

【问题讨论】:

  • 我还以为typedef typename MyBase::InBase&lt;A, B&gt; MyInBase
  • @NeilKirk:试过了,适用于 MSVC,但 GCC 仍然要求 template 关键字。所以它或多或少和以前一样。
  • 您需要typenametemplate。 MSVC 只是在那里不合格。

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


【解决方案1】:

MSVC 在这里拒绝有效代码,正如 N3337 14.2 (temp.names) p4 所述:

当成员模板特化的名称出现在 .-&gt; 之后 postfix-expression 或在 qualified-id 中的 nested-name-specifier 之后,以及 postfix-expression 的对象表达式是类型相关的或 qualified-id中的nested-name-specifier指的是依赖类型,但是名字 不是当前实例化的成员(14.6.2.1),成员模板名称必须 以关键字template 为前缀。否则,该名称被假定为命名一个 非模板。

鉴于此,我在Godbolt 上针对 ICC 13 和 Clang 3.3 检查了您的示例:ICC 正确拒绝了带有 nontype "Base&lt;A, B&gt;::InBase [with A=A, B=B]" is not a template 的 MSVC 主义,同时接受了符合标准的(typename/template 合格)版本,而 Clang ,有趣的是,它同时接受符合的 不符合的 typedef!我的本地 MSVC 11 (VS2012) 副本也拒绝包含 templatetypename 的版本,并按照错误提示传递模板参数列表(无论如何都是不正确的)。

看来 template 关键字也是导致 MSVC 跳闸的原因,这阻止了 GCC 4.9 建议使用其他冗余的 Derived::MyBase::template InBase&lt;A, B&gt; 来强制表达式进入依赖上下文而不使用 typename from工作。

Visual Studio 开发人员已经是aware of a very similar issue to this。至于如何解决它?您只需使用 #ifdef _MSC_VER 块来限制特定于 MSVC 的 typedef 版本。

对于学究:ICC,尽管它在世界的某些角落被撕毁,确实在实践中符合 C++ 标准,因为它使用与 Comeau C++ 相同的 EDG 前端。 p>

【讨论】:

  • 感谢您的详细分析。我目前的解决方法是在没有 ifdefs 的情况下工作,是使用一个结构来包装指针,然后将该结构放入向量中。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多