下面的代码不编译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&) { }仍然会进行编译,除非这次甚至不调用move构造函数(可能是省略)。
最新标准草案的12.6.3说:
1当调用
B类型的构造函数来初始化不同类型D的对象(即当构造函数被继承(namespace.udecl)时)时,初始化将继续进行,就好像使用默认的默认构造函数来初始化D对象和继承构造函数的每个基类子对象一样,但B子对象是通过调用继承的构造函数初始化的。完整的初始化被认为是一个函数调用;特别是,继承构造函数参数的初始化是在初始化D对象的任何部分之前进行的。[例子: 结构B1 { B1(int,.){ };// .struct D1 : B1 {使用B1::B1;//继承B1(int,.)int x;// . };void (){ D1 d(2,3,4);// OK: B1是通过调用B1(2,3,4)初始化的,// d.x是默认初始化(不执行初始化),// .} // .
所以它应该和foo(move_only)完全等价,对吧?
发布于 2016-05-06 06:17:39
这似乎是一个bug (报告为bug 70972)。N4140 N4140./8:
隐式定义的继承构造函数执行由用户为该类编写的内联构造函数所执行的类的初始化集合,该类的mem初始化器-列表中唯一的mem-初始化器-id,它将在使用声明的嵌套名称说明符和表达式列表中表示的基类命名为空(12.6.2)。如果用户编写的构造函数格式不正确,则程序的格式不正确。表达式列表中的每个表达式都是表单
static_cast<T&&>(p),其中p是对应构造函数参数的名称,T是已声明的p类型。
换句话说,这里所讨论的继承构造函数应该是移动而不是复制它的参数。
https://stackoverflow.com/questions/37064993
复制相似问题