'using' 语句用 g++ 编译,用 clang 编译失败
A 'using' statement compiles with g++, fails compilation with clang
我有以下结构的代码(在现实中当然要复杂得多,尤其是 "Base" 是一个三行代码,但我试图抓住它的要点):
template <class T>
class A {};
template <class T>
class B {
public:
B(){};
};
template <class T>
class C : public B<A<T>> {
public:
using Base = B<A<T>>;
using Base::B;
};
static const C<int> c{};
通过
,代码可以通过 g++ 正常编译
g++ -c test.cpp -std=c++11
但是,使用 clang++ 我收到一条我不太理解的错误消息
clang++ -c test.cpp -std=c++11
test.cpp:14:14: error: dependent using declaration resolved to type without 'typename'
using Base::B;
我的代码有什么问题吗?或者这是 clang 中的错误?
注意:在编写 using B<A<T>>::B;
时,它可以在两个编译器上正常编译,但这并不是我的问题的真正解决方案。
编辑:clang版本为3.5.0,gcc版本为4.9.2
来自第 12.1 节:
Constructors do not have names
所以通常的限定查找规则不适用。相反,您必须依赖构造函数查找的特殊规则(第 3.4.3.1 节):
In a lookup in which function names are not ignored and the nested-name-specifier nominates a class C
:
— if the name specified after the nested-name-specifier, when looked up in C
, is the injected-class-name of C
, or
— in a using-declaration (7.3.3) that is a member-declaration, if the name specified after the nested-name-specifier is the same as the identifier or the simple-template-id’s template-name in the last component of the nested-name-specifier,
the name is instead considered to name the constructor of class C
.
所以你当然可以写
using Base::Base;
而不是
using Base::B;
您的原始版本应该在第一个要点下工作,但注入-class-名称在涉及模板时会变得复杂。只需使用更简单的版本 Base::Base
,它也更具可读性。任何看到它的人都会立即知道您正在命名构造函数。
这个案例已经在 C++ 委员会中讨论过(根据 Richard Smith https://llvm.org/bugs/show_bug.cgi?id=23107#c1),现在事情变得更清楚了:
using Base::B
不是有效代码。
下面的方法是引入class别名Base
时构造函数继承的正确表达方式:
using Base::Base
但是,clang 产生的错误消息具有误导性,希望能作为此错误报告的一部分得到解决 (https://llvm.org/bugs/show_bug.cgi?id=22242)。
我有以下结构的代码(在现实中当然要复杂得多,尤其是 "Base" 是一个三行代码,但我试图抓住它的要点):
template <class T>
class A {};
template <class T>
class B {
public:
B(){};
};
template <class T>
class C : public B<A<T>> {
public:
using Base = B<A<T>>;
using Base::B;
};
static const C<int> c{};
通过
,代码可以通过 g++ 正常编译g++ -c test.cpp -std=c++11
但是,使用 clang++ 我收到一条我不太理解的错误消息
clang++ -c test.cpp -std=c++11
test.cpp:14:14: error: dependent using declaration resolved to type without 'typename' using Base::B;
我的代码有什么问题吗?或者这是 clang 中的错误?
注意:在编写 using B<A<T>>::B;
时,它可以在两个编译器上正常编译,但这并不是我的问题的真正解决方案。
编辑:clang版本为3.5.0,gcc版本为4.9.2
来自第 12.1 节:
Constructors do not have names
所以通常的限定查找规则不适用。相反,您必须依赖构造函数查找的特殊规则(第 3.4.3.1 节):
In a lookup in which function names are not ignored and the nested-name-specifier nominates a class
C
:— if the name specified after the nested-name-specifier, when looked up in
C
, is the injected-class-name ofC
, or— in a using-declaration (7.3.3) that is a member-declaration, if the name specified after the nested-name-specifier is the same as the identifier or the simple-template-id’s template-name in the last component of the nested-name-specifier,
the name is instead considered to name the constructor of class
C
.
所以你当然可以写
using Base::Base;
而不是
using Base::B;
您的原始版本应该在第一个要点下工作,但注入-class-名称在涉及模板时会变得复杂。只需使用更简单的版本 Base::Base
,它也更具可读性。任何看到它的人都会立即知道您正在命名构造函数。
这个案例已经在 C++ 委员会中讨论过(根据 Richard Smith https://llvm.org/bugs/show_bug.cgi?id=23107#c1),现在事情变得更清楚了:
using Base::B
不是有效代码。
下面的方法是引入class别名Base
时构造函数继承的正确表达方式:
using Base::Base
但是,clang 产生的错误消息具有误导性,希望能作为此错误报告的一部分得到解决 (https://llvm.org/bugs/show_bug.cgi?id=22242)。