I wonder which parts of the standard specify that in the following code segment:
#include <memory>
class A { };
class B : public A { };
int main()
{
std::unique_ptr<B> bptr = std::make_unique<B>(); // (a)
std::unique_ptr<A> aptr = std::move(bptr); // (b)
std::unique_ptr<A> &aptr_r = bptr; // (c)
std::unique_ptr<A> &&aptr_rr = std::move(bptr); // (d)
return 0;
}
(d) compiles and (c) does not. Please include the relevant parts of the standard in your answer or refer to them appropriately. Just for reference, Ubuntu clang version 3.6.2-1 (tags/RELEASE_362/final) (based on LLVM 3.6.2) gives me
error: non-const lvalue reference to type 'unique_ptr<A>' cannot
bind to a value of unrelated type 'unique_ptr<B>'
std::unique_ptr<A> &aptr_r = bptr;
^ ~~~~
and gcc (Ubuntu 5.2.1-22ubuntu2) 5.2.1 20151010 gives me
error: invalid initialization of reference of type ‘std::unique_ptr<A>&’
from expression of type ‘std::unique_ptr<B>’
std::unique_ptr<A> &aptr_r = bptr;
^
Edit:
To make my question more clear, let me add
class C { };
std::unique_ptr<C> cptr = std::make_unique<C>(); // (e)
std::unique_ptr<A> &&aptr_rr2 = std::move(cptr); // (f)
What is keeping (f) from compiling when (d) does? Obviously A
and C
are unrelated, but where is that detected when the std::unique_ptr
constructor used to construct the temporary for both (d) and (f) is
template<class U, class E>
unique_ptr(unique_ptr<U, E> &&u);