template <typename T>
struct bar: public foo<T>
{
using foo<T>::foo<T>;
};
为了让这个解析正确,您需要在,template
之前插入foo<T>;
,以告诉编译器foo
将被视为模板名称(它无法查看foo<T>
告诉自己,因为T
它是未知的)。但是 using::template
声明中不允许使用 using。该名称也不是指 的所有构造函数bar
:相反,它指的是这样一个构造函数的特定构造函数模板特化(T
是模板参数),如下所示
template<typename T>
foo();
此外, using 声明使用template-id
(like foo<T>
) 作为其名称是无效的(这实际上禁止它引用函数模板特化,另外还声明了对名称转换函数模板特化的禁止),所以即使您使用::template
(如果可能的话) 纠正解析问题,此时您仍然会出错。
引入继承的构造函数时,添加了允许使用句法规则引用构造函数的特殊规则:如果您有一个qualified-id(基本上是一个使用的限定名称...::...
),并且最后一个限定部分之前的最后一个限定名称是一个特定的类,那么您可以通过另外两种方式来表示该类的构造函数:
- 如果该类是使用模板ID(表单的名称
foo<T>
)命名的,并且最后一部分与模板名称匹配(因此,或者foo<T>::foo
作为模板模板参数)。TTP<T>::TTP
TTP
- 如果最后一部分与类名匹配(所以,
foo::foo
或T::T
,T
作为模板参数)。
这两个附加规则仅在 using 声明中有效。它们自然不会出现在 C++03 中。C++03 中也存在的另一条规则是:如果最后部分命名注入的类名,那么这个限定名也指构造函数:
foo::foo
会因此工作。但是仅凭此规则,T::T
(其中T
表示 class foo
)将不起作用,因为foo
没有称为 的成员T
。
因此,有了特殊规则,您可以编写
using foo<T>::foo;
using bar::foo::foo; // valid too
第二个也是有效的:foo
是注入到基类中foo<T>
并继承到的注入类名bar
。我们用 引用该名称bar::foo
,然后添加最后一部分foo
,再次引用注入的类名,以表示 `foo.
现在您明白了为什么您尝试的初始名称会引用构造函数模板特化(如果允许的话):因为该foo<T>::foo
部分将命名所有构造函数,<T>
然后将过滤掉模板并传递类型争论。