【发布时间】:2017-04-17 09:38:32
【问题描述】:
我正在尝试结合使用 C++ 11 直接数据成员初始化和“使用”语法来继承基类的构造函数。现在使用 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 中发现了一个错误。否则,gcc 和 clang 不应该都给我一条错误消息,指出这不是有效的 C++ 11?
在@vlad-from-moscow 很好地回答了这个问题后进行编辑:这个错误似乎也存在于 gcc 6.2 中,所以我将提交一个错误报告。
第二次编辑:已经有一个错误,我在第一次搜索中没有找到:https://gcc.gnu.org/bugzilla/show_bug.cgi?id=67054
【问题讨论】:
-
我在 cppreference.com 等页面上找不到任何相关信息。那里描述了“使用”语法和大括号初始化器,但没有提到任何关于结合两者的内容。
标签: c++ c++11 gcc constructor