Quantcast
Channel: User Peter - Reinstate Monica - Stack Overflow
Viewing all articles
Browse latest Browse all 223

Answer by Peter - Reinstate Monica for Unwanted copy constructor call when creating a shared_ptr

$
0
0

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

Here is a version on godbolt.


Viewing all articles
Browse latest Browse all 223

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>