我有以下结构的代码(实际上当然要复杂得多,特别是" 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:错误:依赖于使用声明解析为没有&#39; typename&#39; 使用Base :: B;
我的代码有什么问题,或者这是clang中的错误吗?
注意:在编写using B<A<T>>::B;
时,它可以很好地编译两个编译器,但这不是我问题的真正解决方案。
编辑:clang版本是3.5.0,gcc版本是4.9.2
答案 0 :(得分:3)
从第12.1节开始:
构造函数没有名称
因此,通常的限定查找规则不适用。相反,您必须依赖构造函数查找的特殊规则(第3.4.3.1节):
在查找中,不忽略函数名称,嵌套名称说明符指定类
C
:- 如果在
C
中查找 nested-name-specifier 之后指定的名称是{{em> inject-name-name {{ 1}},或- using-declaration (7.3.3)成员声明中的,如果在嵌套名称后指定的名称-specifier 与标识符或 simple-template-id 的模板名称在最后一个组件中相同嵌套名称说明符,
而是将名称视为命名类
C
的构造函数。
所以你当然可以写
C
而不是
using Base::Base;
您的原始版本应该在第一个项目符号点下工作,但是当涉及模板时,注入类名称会变得复杂。只需使用更简单的using Base::B;
版本,它更具可读性。任何看到它的人都会立即知道你正在命名一个构造函数。
答案 1 :(得分:3)
这个案例已经在C ++委员会中讨论过(根据理查德史密斯https://llvm.org/bugs/show_bug.cgi?id=23107#c1),现在事情变得更加清晰了:
using Base::B
不是有效代码。
以下方法是在引入类别名Base
时表达构造函数继承的正确方法:
using Base::Base
然而,clang产生的错误消息具有误导性,希望能够作为此错误报告(https://llvm.org/bugs/show_bug.cgi?id=22242)的一部分得到解决。