我有这个简单的代码:
template<template <class> class Generator>
class TestHelper {};
template<class Writer>
class Test
{
typedef TestHelper< Test > Helper;
};
它在最近的g ++版本中运行良好,但是,在4.4或4.5中,我收到此错误:
test.cpp:7: error: type/value mismatch at argument 1 in template parameter list for 'template<template<class> class Generator> class TestHelper'
test.cpp:7: error: expected a class template, got 'Test<Writer>'
我做错了什么?
答案 0 :(得分:12)
这是因为在类Test<Writer>
的正文中,在不提供模板参数的情况下命名Test
会自动采用相同的参数(例如Writer
)。
例如,这允许您将复制构造函数编写为:
Test(const Test&);
而不是
Test::Test(const Test<Writer>&);
您可以通过使用其名称空间限定Test
来解决此问题,例如
typedef TestHelper< ::Test > Helper;
注意:正如Tomalek建议的那样,原始用法在C ++ 0x中有效。以下是标准(强调我的)的相关段落,来自第14.6.1节([temp.local]
):
与普通(非模板)类一样,类模板具有注入类名(第9节)。 inject-class-name可以用作模板名称或类型名称。 使用时使用 template-argument-list ,作为模板的模板参数 template-parameter ,或作为朋友类模板声明的 elaborated-type-specifier 中的最终标识符,它指的是类模板本身。否则,它等同于 template-name ,后跟&lt;&gt;中包含的类模板的 template-parameters 。
答案 1 :(得分:1)
@Ben可能是正确的,但这是一种完全不同的方式来编译它,不使用模板作为模板的args。
template<class Generator> // changed this to a simpler template
class TestHelper {};
template<class Writer>
class Test
{
typedef TestHelper< typename Test :: Writer > Helper; // 2nd change
};
我做了两处修改。 @Hugo,也许这就是你想要的,也许这就是旧版本的g ++所做的?
编译代码很容易,但这并不意味着它会按照你的想法做到!