gpt4 book ai didi

c++ - 在这种情况下,Hinnant 的 unique_ptr 实现是否错误地无法将派生转换为基础?

转载 作者:太空狗 更新时间:2023-10-29 23:10:07 27 4
gpt4 key购买 nike

我目前正在尝试使用 Howard Hinnant's unique_ptr implementation ,并且遇到编译错误。这是一些示例代码:

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
}

我得到的错误是

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>]'

看起来违规行应该不会失败。这是实现中的错误,是由于缺少 C++0x 语言特性导致的实现限制,还是对 unique_ptrs 规则的误解?

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

最佳答案

类似的例子,看这个也应该失败

unique_ptr<Base> testBase = move(testDerived);

这里的问题是移动语义是如何实现的:“复制构造函数”采用非常量引用,因此无法绑定(bind)到临时对象。为了仍然从临时对象“移动”,该类有一个转换函数(以下只是概念上的——它们可能在细节上有不同的实现):

operator rv<T>() { return rv<T>(*this); }

构造函数将获取该对象:

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();

复制初始化将首先转换为A。但是随后,尝试将临时 A 对象再次复制到最终对象。这将需要使用 operator E 的方式。但这是初始化中另一个用户定义的转换,标准禁止这样做:

13.3.3.1/4

When invoked for the copying of the temporary in the second step of a class copy-initialization, [...], only standard conversion sequences and ellipsis conversion sequences are allowed.

这就是您的代码失败的原因。

关于c++ - 在这种情况下,Hinnant 的 unique_ptr 实现是否错误地无法将派生转换为基础?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2365031/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com