C++ Hinnant';在这种情况下,s unique_ptr实现无法正确地将派生转换为基?

C++ Hinnant';在这种情况下,s unique_ptr实现无法正确地将派生转换为基?,c++,unique-ptr,C++,Unique Ptr,我目前正在尝试使用,但遇到了编译错误。以下是一些示例代码: struct Base {}; struct Derived : public Base {}; void testfun(boost::unique_ptr<Base>); void test() { unique_ptr<Derived> testDerived; unique_ptr<Base> testBase(move(testDerived)); // ok, co

我目前正在尝试使用,但遇到了编译错误。以下是一些示例代码:

struct Base {};

struct Derived : public Base {};

void testfun(boost::unique_ptr<Base>);

void test()
{
    unique_ptr<Derived> testDerived; 
    unique_ptr<Base> testBase(move(testDerived)); // ok, construct base explicitly from derived 
    testfun(move(testBase));                      // ok, pass base to testfun which expects base 
    testfun(unique_ptr<Base>(move(testDerived))); // ok, explicitly converts to unique_ptr<Base>
    testfun(move(testDerived));                   // error on this line
}
struct Base{};
派生结构:公共基{};
void testfun(boost::unique_ptr);
无效测试()
{
唯一的_ptr testDerived;
unique_ptr testBase(move(testDerived));//好的,从派生的
testfun(move(testBase));//好,将base传递给需要base的testfun
testfun(unique_ptr(move(testDerived));//好,显式转换为unique_ptr
testfun(move(testDerived));//此行出错
}
我得到的错误是

In function 'void test()':
error: no matching function for call to 'boost::unique_ptr<Base, boost::default_delete<Base> >::unique_ptr(boost::unique_ptr<Base, boost::default_delete<Base> >)'
note: candidates are: boost::unique_ptr<T, D>::unique_ptr(boost::detail_unique_ptr::rv<boost::unique_ptr<T, D> >) [with T = Base, D = boost::default_delete<Base>]
note:                 boost::unique_ptr<T, D>::unique_ptr(boost::unique_ptr<T, D>&) [with T = Base, D = boost::default_delete<Base>]
error:   initializing argument 1 of 'void testfun(boost::unique_ptr<Base, boost::default_delete<Base> >)' from result of 'boost::unique_ptr<T, D>::unique_ptr(boost::unique_ptr<U, E>, typename boost::enable_if_c<((((! boost::is_array<U>::value) && boost::detail_unique_ptr::is_convertible<typename boost::unique_ptr<U, boost::default_delete<U> >::pointer,typename boost::detail_unique_ptr::pointer_type<T, D>::type>::value) && boost::detail_unique_ptr::is_convertible<E,D>::value) && ((! boost::is_reference<D>::value) || boost::is_same<D,E>::value)), void>::type*) [with U = Derived, E = boost::default_delete<Derived>, T = Base, D = boost::default_delete<Base>]'
函数“void test()”中的
:
错误:调用“boost::unique_ptr::unique_ptr(boost::unique_ptr)”时没有匹配函数
注:候选项为:boost::unique\u ptr::unique\u ptr(boost::detail\u unique\u ptr::rv)[带T=Base,D=boost::default\u delete]
注意:boost::unique_ptr::unique_ptr(boost::unique_ptr&)[带T=Base,D=boost::default_delete]
错误:根据“boost::unique_ptr::unique_ptr(boost::unique_ptr,typename boost::enable_if_c::type*)的结果初始化“void testfun(boost::unique_ptr)”的参数1[其中U=Derived,E=boost::default_delete,T=Base,D=boost::default_delete]'
似乎冒犯者的路线不应该失败。这是实现中的一个bug,是由于缺乏C++0x语言功能而导致的实现限制,还是对unique_ptr规则的误解


(注意,我知道这在运行时不起作用,因为我不止一次地移动同一个东西;我只是试图找出编译时错误。)

有关类似的示例,请参阅此示例,它也应该失败

unique_ptr<Base> testBase = move(testDerived);
复制初始化将首先转换为
A
。但是,临时
对象将再次尝试复制到最终对象。这将需要使用
运算符E
的方法。但这是初始化中的另一个用户定义转换,标准禁止:

13.3.3.1/4

在类复制初始化的第二步[…]中调用临时复制时,只允许标准转换序列和省略号转换序列


这就是代码失败的原因

进一步的研究使我相信,这是一个已知的实施限制:

我目前有3个测试失败(编译时失败, 应该编译、运行和传递)。这些都与 正在转换[unique.ptr.single.ctor]中指定的构造函数。什么时候 源和目标是不同类型的,这种仿真需要 转换必须是显式的,并且拒绝在隐式上编译 转换:

unique_ptr<base> b(unique_ptr<derived>()); // ok

unique_ptr<base> b = unique_ptr<derived>(); // causes 3 compile time failures under unique.ptr/unique.ptr.single/unique.ptr.single.ctor .
unique_ptr b(unique_ptr());//好啊
唯一的_ptrb=唯一的_ptr();//在unique.ptr/unique.ptr.single/unique.ptr.single.ctor下导致3次编译时失败。

描述的关键部分可能是“此仿真旨在捕获C++0X unique\u ptr的大部分行为…”。我认为这意味着并不是所有的行为都存在。下面是导致C++03这种行为的论文:litb的writeup提供了大量信息,但我认为这是对这个问题更直接的回答。双方均应阅读:-)
unique_ptr(rv<T> r):ptr_(r.release()) { }
// move helper. rv<> in unique_ptr
struct E { };

// simulates a unique_ptr<D>
struct D { };

// simulates the unique_ptr<B>
struct A {
  A() { }

  // accepts "derived" classes. Note that for unique_ptr, this will need that
  // the argument needs to be copied (we have a by-value parameter). Thus we 
  // automatically ensure only rvalue derived-class pointers are accepted.
  A(D) { } 

  // these will accept rvalues
  A(E) { }
  operator E() { return E(); }

private:
  A(A&); // private, error if passed lvalue
};
// allowed: goes: D -> A(D)
A a((D()));

// compile failure. Goes:
// D -> A(D) -> A(E)
A a = D();
unique_ptr<base> b(unique_ptr<derived>()); // ok

unique_ptr<base> b = unique_ptr<derived>(); // causes 3 compile time failures under unique.ptr/unique.ptr.single/unique.ptr.single.ctor .