我正在尝试使用C++11直接数据成员初始化和 "using" 语法来继承基类的构造函数。现在在gcc 5.4.0(Ubuntu 16.04)下,如果数据成员类型没有默认构造函数,则会出现奇怪的错误。最简单的例子如下:
#include <iostream>
struct Foo {
Foo(int arg) { std::cout << "Foo::Foo(" << arg << ")" << std::endl; }
};
struct Base {
Base(int arg) { std::cout << "Base::Base(" << arg << ")" << std::endl; }
};
struct Derived : public Base {
using Base::Base;
Foo foo{42};
};
int main() {
Derived derived{120};
}
这段代码在clang下编译和执行时表现符合预期。但在gcc下无法编译,因为编译器删除了构造函数Derived::Derived(int)
。
ttt.cpp: In function ‘int main()’:
ttt.cpp:17:22: error: use of deleted function ‘Derived::Derived(int)’
Derived derived{120};
^
ttt.cpp:12:15: note: ‘Derived::Derived(int)’ is implicitly deleted because the default definition would be ill-formed:
using Base::Base;
^
ttt.cpp:12:15: error: no matching function for call to ‘Foo::Foo()’
ttt.cpp:4:3: note: candidate: Foo::Foo(int)
Foo(int arg) { std::cout << "Foo::Foo(" << arg << ")" << std::endl; }
^
ttt.cpp:4:3: note: candidate expects 1 argument, 0 provided
ttt.cpp:3:8: note: candidate: constexpr Foo::Foo(const Foo&)
struct Foo {
^
ttt.cpp:3:8: note: candidate expects 1 argument, 0 provided
ttt.cpp:3:8: note: candidate: constexpr Foo::Foo(Foo&&)
ttt.cpp:3:8: note: candidate expects 1 argument, 0 provided
如果我像这样为Foo添加默认构造函数:
Foo() { std::cout << "Foo::Foo()" << std::endl; };
同时gcc也可以编译它。代码的行为完全相同,尤其是Foo的默认构造函数未被执行。
所以我的问题是,这是有效的C++11吗?如果是,那么我可能已经发现了gcc的一个bug。否则,gcc和clang都不应该给我一个错误消息,说明这不是有效的C++11吗?
在@vlad-from-moscow很好地回答了我的问题后进行编辑:这个bug似乎也存在于gcc 6.2中,所以我将提交一个bug报告。
第二次编辑:我没有在第一次搜索中找到的一个bug已经存在:https://gcc.gnu.org/bugzilla/show_bug.cgi?id=67054