Your complicated nested pointers obscure the underlying issue somewhat. Ownership is not really the issue here, and there is no issue creating a shared_ptr from a unique_ptr. The error you get concerns solely the unique_ptr. Here the mentioned "obscuring" becomes noticeable because the error is hard to understand. But if I cut all the fluff like std:: and template parameters, it boils down to
use of deleted function unique_ptr::unique_ptr(const unique_ptr &),
which is the copy constructor. The copy constructor for unique_ptr is deleted because a unique_ptr cannot be copied; it is, after all, unique.
But why is the copy constructor selected at all by overload resolution? Because the declared move constructor moves from an rvalue reference which is not const. A const rvalue reference is simply not a match. The fallback then is an attempt to use the copy constructor since a const reference can be bound to a constant rvalue reference; but that one is, as we said, deleted for good reasons.
Below is code which demonstrates the workings with a trivial class S. Your constructor case is demonstrated with test_class
, but the easiest demonstration is actually the last line in main()
: You simply cannot construct an S
from a const rref. The case that an S
may be a member of a different class and the construction is part of that class's initialization is not really important to the problem.
#include <utility> // std::moveusing namespace std;// this takes on the role of unique_ptr in your examplestruct S { S() = default; // [1] enable the copy constructor ... //S(const S&) = default; // [2] ... or the move constructor from rref to const; //S(const S&&) {} // [3] OR remove the move constructor; that will un-delete the copy ctor S(S&&) = default;};class test_class{ public: S _s; // Does not work because no constructor matches. In the order of // resolution attempts: // 1. The best match, a constructor taking a const rref argument, is not declared, see [2] // 2. The declared regular move constructor [3] taking a non-const rref argument does not match; // 3. The regular copy constructor taking a const ref argument // is implicitly deleted because we declared a move constructor [3]. // We could explicitly define it, [1] // test_class(const S &sArg): _s{move(sArg)} {} };int main(){ const S cs; // move actually works like a charm but produces an rref to const. const S &&s_rref{move(cs)}; // construction from a const rref is not defined. // S s{move(cs)};}