2

我正在尝试使用 g++ 4.9.0 编译以下简单代码:

struct A {
    explicit A(int x) { }
};

struct B : public virtual A {
    using A::A;
};

int main(int argc, char** argv) {
    B b(0);
    return 0;
}

但我收到以下错误:

$ g++ -std=c++11 main.cpp
main.cpp: In function ‘int main(int, char**)’:
main.cpp:10:10: error: use of deleted function ‘B::B(int)’
     B b(0);
          ^
main.cpp:6:14: note: ‘B::B(int)’ is implicitly deleted because the default definition would be ill-formed:
     using A::A;
              ^
main.cpp:6:14: error: no matching function for call to ‘A::A()’
main.cpp:6:14: note: candidates are:
main.cpp:2:14: note: A::A(int)
     explicit A(int x) { }
              ^
main.cpp:2:14: note:   candidate expects 1 argument, 0 provided
main.cpp:1:8: note: constexpr A::A(const A&)
 struct A {
        ^
main.cpp:1:8: note:   candidate expects 1 argument, 0 provided
main.cpp:1:8: note: constexpr A::A(A&&)
main.cpp:1:8: note:   candidate expects 1 argument, 0 provided

难道我做错了什么?它是编译器错误吗?

4

2 回答 2

4

这是一个GCC 错误。§7.3.3 [namespace.udecl]/p3 要求

在用作member-declaration的using-declaration中, nested-name-specifier应命名正在定义的类的基类。如果这样的using-declaration命名了一个构造函数,则 nested-name-specifier应命名正在定义的类的直接基类...

A是 的直接基数B,因此using A::A;是允许的。

该标准规定(§12.9 [class.inhctor]/p8):

隐式定义的继承构造函数执行类的一组初始化,这些初始化将由用户编写 inline的具有mem-initializer-list的类的构造函数执行,该类的唯一mem-initializer具有命名基的mem-initializer-id在 using 声明的嵌套名称说明符和下面指定的表达式列表中表示的类,并且其函数体中的复合语句为空 (12.6.2)。如果该用户编写的构造函数格式错误,则程序格式错误。表达式列表中的每个表达式的格式为 static_cast<T&&>(p),其中p是相应构造函数参数的名称,并且T是 的声明类型p

因此相应的用户编写的构造函数是

B::B(int x) : A(static_cast<int&&>(x)) { }

这是格式良好的。

于 2014-09-03T21:20:05.647 回答
1

它似乎用 clang 编译,但不是 gcc(至少在我的机器上)。但是,即使使用 gcc,如果您只是将构造函数添加到基类,代码也可以编译并正常工作。explicit A()

编辑显然,正如@TC 评论中所指出的,这是 GCC 中的一个已知错误

于 2014-09-03T21:12:20.830 回答