简体   繁体   English

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

[英]MSVC: “use of class template requires template argument list” inside STL containers

I have an issue with nested template classes on MSVC 12 and GCC 4.8. 我在MSVC 12和GCC 4.8上的嵌套模板类有问题。 I've reduced it to the following snippet: 我将其简化为以下代码段:

#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;
};

When I use the MSVC variant of MyInBase on GCC, it just tells me to add typename and template , which I find understandable. 当我在GCC上使用MyInBase的MSVC变体时,它只是告诉我添加typenametemplate ,我认为这是可以理解的。 When I use the GCC variant on MSVC (which I believe is the correct one), it reports this: 当我在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'

Is the MSVC error correct? MSVC错误正确吗? If yes, how can I fix it? 如果是,我该如何解决?

MSVC is rejecting valid code here, as N3337 14.2 (temp.names) p4 states: MSVC在这里拒绝有效代码,因为N3337 14.2(临时名称)p4指出:

When the name of a member template specialization appears after . 当成员模板专门化名称出现在之后. or -> in a postfix-expression or after a nested-name-specifier in a qualified-id , and the object expression of the postfix-expression is type-dependent or the nested-name-specifier in the qualified-id refers to a dependent type, but the name is not a member of the current instantiation (14.6.2.1), the member template name must be prefixed by the keyword template . ->postfix-expression中,或者在qualified-id中嵌套名称说明符之后,并且postfix-expression的对象表达式取决于类型,或者qualified-id中nested-name-specifier引用一个依赖类型,但名称不是当前实例(14.6.2.1)的成员,成员模板名称必须以关键字template为前缀。 Otherwise the name is assumed to name a non-template. 否则,假定该名称命名为非模板。

Given this, I checked your sample against ICC 13 and Clang 3.3 on Godbolt : ICC correctly rejects this MSVC-ism with nontype "Base<A, B>::InBase [with A=A, B=B]" is not a template while accepting the conformant ( typename / template qualified) version, whereas Clang, interestingly enough, accepts both the conformant and the nonconformant typedefs! 鉴于此,我在Godbolt上针对ICC 13和Clang 3.3检查了您的示例:ICC正确拒绝了nontype "Base<A, B>::InBase [with A=A, B=B]" is not a template MSVC-ism nontype "Base<A, B>::InBase [with A=A, B=B]" is not a template在接受符合的( typename / template合格)版本,而铛,有趣的是,同时接受的符合性不符合标准的typedef! My local copy of MSVC 11 (VS2012) also rejects the version with template and typename in it, as well as passing a template argument list as the error suggests (which is ill-formed in any case). 我在本地的MSVC 11(VS2012)副本也拒绝其中带有templatetypename的版本,并拒绝错误提示的模板参数列表(无论如何格式错误)。

It appears that the template keyword is what is tripping MSVC up, too, which prevents GCC 4.9's suggestion of using an otherwise-redundant Derived::MyBase::template InBase<A, B> to force the expression into a dependent context without using typename from working. 看来template关键字也是使MSVC Derived::MyBase::template InBase<A, B> ,这也阻止了GCC 4.9建议使用否则为冗余的Derived::MyBase::template InBase<A, B>来强制表达式进入依赖上下文而没有使用typename从工作。

The Visual Studio devs are already aware of a very similar issue to this . Visual Studio开发人员已经意识到与此类似的问题 As to working around it, though? 至于如何解决呢? You'll just have to use a #ifdef _MSC_VER block to cage the MSVC-specific version of the typedef. 您只需要使用#ifdef _MSC_VER块来笼罩特定于MSVC的typedef版本。

For pedants: ICC, for all it gets ripped on in some corners of the world, does conform to the C++ standards in practice, as it uses the same EDG frontend as Comeau C++. 对于pedant:ICC,尽管它在世界的某些角落被撕破了, 但实际上它符合C ++标准,因为它使用了与Comeau C ++相同的EDG前端。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM