【发布时间】:2016-09-01 02:11:12
【问题描述】:
以下代码不能编译GCC 6.1,但可以在Clang 3.8.0 和Visual Studio 2015 中工作:
#include <memory>
class base {
public:
base(std::unique_ptr<int>) {}
};
class derived : public base {
public:
using base::base;
};
int main() {
derived df(std::make_unique<int>());
}
出现以下错误:
main.cpp: In constructor 'derived::derived(std::unique_ptr<int>)':
main.cpp:10:17: error: use of deleted function
'std::unique_ptr<_Tp, _Dp>::unique_ptr(const std::unique_ptr<_Tp, _Dp>&)
[with _Tp = int; _Dp = std::default_delete<int>]'
using base::base;
^~~~
In file included from /usr/local/include/c++/6.1.0/memory:81:0,
from main.cpp:1:
/usr/local/include/c++/6.1.0/bits/unique_ptr.h:356:7: note: declared here
unique_ptr(const unique_ptr&) = delete;
^~~~~~~~~~
main.cpp: In function 'int main()':
main.cpp:14:39: note: synthesized method 'derived::derived(std::unique_ptr<int>)'
first required here
derived df(std::make_unique<int>());
它似乎正在尝试调用已删除的复制构造函数,但这工作得很好:
void foo(std::unique_ptr<int>) {}
int main() {
foo(std::make_unique<int>());
}
这个带有-fno-elide-constructors 的示例打印出move called.:
struct move_only {
move_only() { std::cout << "default called."; }
move_only(move_only&&) { std::cout << "move called."; }
};
void foo(move_only) { }
int main() {
foo(move_only{});
}
我意识到这两种情况并不相同,但似乎很奇怪&& 需要编译继承的构造函数示例而不是后者。作为健全性检查,显式执行move_only(const move_only&) = delete; 并将签名更改为void foo(const move_only&) { } 仍然可以编译,除了这次甚至没有调用移动构造函数(可能是省略)。
12.6.3的最新标准草案说:
1 当调用
B类型的构造函数来初始化对象时 不同类型的D(即,当构造函数被继承时 ([namespace.udecl])),初始化就像默认的 默认构造函数用于初始化 D 对象和每个基 继承构造函数的类子对象,除了 B 子对象由继承的调用初始化 构造函数。完整的初始化被认为是一个单一的 函数调用;特别是继承的初始化 构造函数的参数在任何初始化之前排序D对象的一部分。 [ 例子:struct B1 { B1(int, ...) { } }; // ... struct D1 : B1 { using B1::B1; // inherits B1(int, ...) int x; // ... }; void test() { D1 d(2, 3, 4); // OK: B1 is initialized by calling B1(2, 3, 4), // then d.x is default-initialized (no initialization is performed), // ... } // ...
所以它应该完全等同于foo(move_only) 对吧?
【问题讨论】:
-
继承构造函数语义在当前工作草案中经历了a giant overhaul;还没有人实施新版本。
-
看起来像是 g++ 6.1 中的回归。 It compiles 在 g++5.3 中
标签: c++ gcc c++14 move-semantics