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>::TTPTTP
- 如果最后一部分与类名匹配(所以,
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>然后将过滤掉模板并传递类型争论。