'using'语句使用g ++编译,无法使用clang进行编译

时间:2015-01-15 00:26:00

标签: c++ compilation g++ 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:错误:依赖于使用声明解析为没有&#39; typename&#39;         使用Base :: B;

我的代码有什么问题,或者这是clang中的错误吗?

注意:在编写using B<A<T>>::B;时,它可以很好地编译两个编译器,但这不是我问题的真正解决方案。

编辑:clang版本是3.5.0,gcc版本是4.9.2

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)的一部分得到解决。