我在 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 错误是否正确?如果是,我该如何解决?
最佳答案
MSVC 在此拒绝有效代码,如 N3337 14.2 (temp.names) 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 keywordtemplate
. Otherwise the name is assumed to name a non-template.
鉴于此,我在 Godbolt 上对照 ICC 13 和 Clang 3.3 检查了您的示例:ICC 正确地拒绝了这种 MSVC 主义 nontype "Base<A, B>::InBase [with A=A, B=B]" is not a template
同时接受一致的( typename
/template
限定)版本,而有趣的是,Clang 既接受一致的 又 不一致的 typedef!我的 MSVC 11 (VS2012) 本地拷贝也拒绝带有 template
的版本和typename
其中,以及按照错误提示传递模板参数列表(在任何情况下都是格式错误的)。
看来 template
关键字也是导致 MSVC 失败的原因,它阻止了 GCC 4.9 使用其他冗余的建议 Derived::MyBase::template InBase<A, B>
强制表达式进入依赖上下文而不使用 typename
从工作中。
Visual Studio 开发人员已经 aware of a very similar issue to this 。不过,至于解决这个问题吗?您只需使用 #ifdef _MSC_VER
block 来限制 MSVC 特定版本的 typedef。
对于学究来说:ICC,尽管它在世界某些角落被蹂躏,但在实践中确实符合 C++ 标准,因为它使用与 Comeau C++ 相同的 EDG 前端。
关于c++ - MSVC : "use of class template requires template argument list" inside STL containers,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26037290/