您可以使用构造函数链来修复它:
struct derive : base
{
private:
derive(const D& some_data, unique_ptr<X>&& ptr) : base{some_data, std::move(ptr)} {}
public:
derive(unique_ptr<X> ptr): derive(func(ptr->some_data), std::move(ptr)) {}
};
原因:正如我在其他答案中所解释的,致电func
肯定发生在委托构造函数调用之前,同时实际移动unique_ptr
(而不是仅仅改变其价值类别)肯定发生在内部。
当然,这依赖于另一个 C++11 功能,Visual C++ 可能正确也可能不正确。令人高兴的是,自 VS2013 起,委派构造函数被列为受支持.
更好的事情就是总是接受std::unique_ptr
通过引用传递参数,如果您打算窃取参数,则通过右值引用传递参数。 (如果你不会窃取内容,为什么你关心调用者拥有什么类型的智能指针?只需接受一个原始的T*
.)
如果你用过
struct base
{
virtual ~base() = 0 {}
protected:
base(std::unique_ptr<base>&& new_state) :
previous_state{ std::move(new_state) } {}
private:
std::unique_ptr<base> previous_state;
};
struct derive_base : base
{
int get_a() const noexcept {
return a;
}
protected:
derive_base(int const new_a, std::unique_ptr<base>&& new_state) :
base{ std::move(new_state) }, a{ new_a } {}
private:
int a;
};
struct final_state : derive_base
{
final_state(std::unique_ptr<base>&& new_state) :
derive_base{ dynamic_cast<derive_base&>(*new_state).get_a(), std::move(new_state) } {}
};
你一开始就不会遇到这个问题,并且调用者的要求完全不变(必须提供右值,因为unique_ptr
无论如何是不可复制的)
使其成为通用规则的基本原理如下:按值传递允许复制或移动,以调用站点上更佳的为准。但std::unique_ptr
是不可复制的,因此实际参数无论如何都必须是右值。