title: How to avoid move semantics for class members?
body: <p><strong>Example:</strong><br>
  I have the following code (reduced to model example, Qt library used, Qt classes behavior explained below):</p>
  
  <pre><code>struct Test_impl {
    int x;
    Test_impl() : x(0) {}
    Test_impl(int val) : x(val) {}
  };
  
  class Test {
    QSharedPointer&lt;Test_impl&gt; m;
  public:
    Test() : m(new Test_impl()) {}
    Test(int val) : m(new Test_impl(val)) {}
    void assign(const QVariant&amp; v) {m = v.value&lt;Test&gt;().m; ++m-&gt;x;}
    ~Test(){--m-&gt;x;}
  };
  
  Q_DECLARE_METATYPE(Test)
  </code></pre>
  
  <p><code>QSharedPointer</code> is a smart pointer implementing move semantic (which is omitted in documentation). <code>QVariant</code> is somewhat similar to <code>std::any</code> and has the template method</p>
  
  <pre><code>template&lt;typename T&gt; inline T value() const;
  </code></pre>
  
  <p>Macro <code>Q_DECLARE_METATYPE</code> allows values of type <code>Test</code> to be placed inside a <code>QVariant</code>.</p>
  
  <p><strong>Problem:</strong><br>
  Line <code>m = v.value&lt;Test&gt;().m;</code> seemingly invokes move assignment for the field <code>m</code> of a temporary object returned by <code>value()</code>. After that, <code>Test</code> destructor is called and promptly crashes trying to access illegal address.<br>
  Generally, the problem as I see it is that while move assignment leaves the object itself in a consistent state, state of an object containing moved entity "unexpectedly" changes.  </p>
  
  <p>There are several ways to avoid the problem in this particular example I can think of: change <code>Test</code> destructor to expect null <code>m</code>, write template <code>template&lt;typename T&gt; inline T no_move(T&amp;&amp; tmp) {return tmp;}</code>, explicitly create temporary <code>Test</code> object in <code>assign</code>, add getter for <code>m</code> and call it to force copying <code>m</code> (advised by <a href="https://stackoverflow.com/users/2684539/jarod42">Jarod42</a>); MS Visual Studio allows to write <code>std::swap(m, v.value&lt;Test&gt;().m)</code>, but this code is illegal.</p>
  
  <p><strong>Question(s):</strong><br>
  Is there a "proper" (best practice?) way to explicitly invoke copy assignment (or somehow properly invoke <code>swap</code>) instead of move? Is there a way to prohibit move semantics for class fields used in the destructor? Why moving a temporary object member was made a default option in the first place?</p>