Note that there are some explanatory texts on larger screens.

plurals
  1. POHow to copy (or swap) objects of a type that contains members that are references or const?
    text
    copied!<p>The problem I am trying to address arises with making containers such as an <code>std::vector</code> of objects that contain reference and const data members:</p> <pre><code>struct Foo; struct Bar { Bar (Foo &amp; foo, int num) : foo_reference(foo), number(num) {} private: Foo &amp; foo_reference; const int number; // Mutable member data elided }; struct Baz { std::vector&lt;Bar&gt; bar_vector; }; </code></pre> <p>This won't work as-is because the default assignment operator for class <code>Foo</code> can't be built due to the reference member <code>foo_reference</code> and const member <code>number</code>.</p> <p>One solution is to change that <code>foo_reference</code> to a pointer and get rid of the <code>const</code> keyword. This however loses the advantages of references over pointers, and that <code>const</code> member really should be <code>const</code>. They are private members, so the only thing that can do harm is my own code, but I have shot myself in the foot (or higher) with my own code.</p> <p>I've seen solutions to this problem on the web in the form of <code>swap</code> methods that appear to be chock full of undefined behavior based on the wonders of <code>reinterpret_cast</code> and <code>const_cast</code>. It happens that those techniques do appear to work on my computer. Today. With one particular version of one particular compiler. Tomorrow, or with a different compiler? Who knows. I am not going to use a solution that relies on undefined behavior.</p> <p>Related answers on stackoverflow:</p> <ul> <li><a href="https://stackoverflow.com/questions/3658854/c-implement-the-copy-assignment-operator-in-a-class-with-all-const-data-mem">Does it make sense to implement the copy-assignment operator in a class with all const data members?</a><br> The first answer has the amusing line "If that one is immutable, your screwed."</li> <li><a href="https://stackoverflow.com/questions/2210388/swap-method-with-const-members">Swap method with const members</a><br> The first answer doesn't really apply here, and the second is a bit of a kludge.</li> </ul> <p>So is there a way to write a <code>swap</code> method / copy constructor for such a class that does not invoke undefined behavior, or am I just screwed?</p> <p><strong>Edit</strong><br> Just to make it clear, I already am quite aware of this solution:</p> <pre><code>struct Bar { Bar (Foo &amp; foo, int num) : foo_ptr(&amp;foo), number(num) {} private: Foo * foo_ptr; int number; // Mutable member data elided }; </code></pre> <p>This explicitly eliminates the <code>const</code>ness of <code>number</code> and the eliminates the implied <code>const</code>ness of <code>foo_reference</code>. This is not the solution I am after. If this is the only non-UB solution, so be it. I am also quite aware of this solution:</p> <pre><code>void swap (Bar &amp; first, Bar &amp; second) { char temp[sizeof(Bar)]; std::memcpy (temp, &amp;first, sizeof(Bar)); std::memcpy (&amp;first, &amp;second, sizeof(Bar)); std::memcpy (&amp;second, temp, sizeof(Bar)); } </code></pre> <p>and then writing the assignment operator using copy-and-swap. This gets around the reference and const problems, but is it UB? (At least it doesn't use <code>reinterpret_cast</code> and <code>const_cast</code>.) Some of the elided mutable data are objects that contain <code>std::vector</code>s, so I don't know if a shallow copy like this will work here.</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload