【发布时间】:2014-11-14 15:26:48
【问题描述】:
在阅读this question时,我发现了一个奇怪的地方:
template <typename T>
class Subclass : public Baseclass<T>
{
public:
using typename Baseclass<T>::Baseclass;
// ^^^^^^^^
};
由于typename,Baseclass<T>::Baseclass 应该是injected class name,而不是构造函数。据我所知,和这个是一样的情况:
template <typename T>
class Base
{
public:
typedef short some_type;
};
template <typename T>
class Sub : public Base<T>
{
public:
using typename Base<T>::some_type;
};
为了确保,我写了一个测试代码。
#include <iostream>
template <typename T>
class Base
{
public:
Base() { std::cout << "A::A()\n"; }
Base(int) { std::cout << "A::A(int)\n"; }
Base(const char *) { std::cout << "A::A(const char *)\n"; }
};
template <typename T>
class Sub : public Base<T>
{
using typename Base<T>::Base;
};
int main()
{
Sub<char> s1;
Sub<char> s2(3);
Sub<char> s3("asdf");
}
但是,它在 gcc 4.8.3 上运行。
$ g++ -std=c++1y -Wall -Wextra -Werror -pedantic test.cpp -o test && ./test
A::A()
A::A(int)
A::A(const char *)
它也可以在没有 typename 的情况下运行。
$ cat test.cpp
...
using Base<T>::Base;
...
$ g++ -std=c++1y -Wall -Wextra -Werror -pedantic test.cpp -o test && ./test
A::A()
A::A(int)
A::A(const char *)
为什么我会得到这些结果?我错过了什么?
【问题讨论】:
-
clang++ 拒绝
typename。 -
我太在意自己的理智,无法回答另一个问题...标准在 [namespace.udecl]/1 中说:“如果 using-declaration 名称构造函数,它在出现 using-declaration 的类中隐式声明一组构造函数;否则,在 using-declaration 中指定的名称是名称的同义词在别处声明的某个实体。”但在 [class.ctor]/1 “构造函数没有名称。”
-
注意这里有 [namespace.udecl]/20 "如果一个using-declaration 使用关键字
typename并指定一个从属名称,则由using-declaration 被视为 typedef-name。" -
@dyp 哦,复制粘贴也是一样的错字;;反正我和clang好像是对的; gcc 似乎在详细标准上有一些错误。
-
规则是“在不忽略函数名并且 nested-name-specifier 指定一个类 C 的查找中:- 如果在 nested-name-specifier,当在 C 中查找时,是 C 的 injected-class-name(第 9 条)[...] 该名称被认为是命名C 类的构造函数。" ([class.qual]/p2)
标签: c++ language-lawyer typename using-declaration inheriting-constructors