Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>Constraints of generic programming are best stated in terms of expressions. A more modern rendition of the same constraint on copiability would be that both statements should be valid:</p> <pre><code>T b = a; </code></pre> <p>and</p> <pre><code>T b = ra; </code></pre> <p>where <code>a</code> is an lvalue with type <code>T</code> or <code>const T</code> and <code>ra</code> is an rvalue with type <code>T</code> or <code>const T</code>. (With similar post-conditions.)</p> <p>This formulation is in the spirit of the paper, I believe. Do note that C++03 already makes use of notions like lvalues and rvalues, such that the constraint we've expressed requires that something like <code>T source(); T b = source();</code> be valid -- certainly something that seems sensible.</p> <p>Under those constraints, then not much changes with C++11. Of particular note is that such a (pathological) type is irregular:</p> <pre><code>struct irregular { irregular() = default; irregular(irregular const&amp;) = default; irregular&amp; operator=(irregular const&amp;) = default; irregular(irregular&amp;&amp;) = delete; irregular&amp; operator=(irregular&amp;&amp;) = delete; }; </code></pre> <p>because something like <code>irregular a; irregular b = a;</code> is valid while <code>irregular source(); irregular b = source();</code> isn't. It's a type that is somewhat copyable (resp. copy assignable), but not quite enough. [ This has been considered somewhat of a defect and is slated to be changed for C++1y, where such a type will in fact be copyable. ]</p> <p>Going further, for the post-condition that a copy must be equivalent in some sense to the original (or, for rvalues, to the original before the copy) to hold, a move special member can only ever be an 'optimization' of the respective copy special member. Another way to put it is that copy semantics are a refinement of move semantics. This means that the assertion must hold in the following:</p> <pre><code>T a; T b = a; T c = std::move(a); assert( b == c ); </code></pre> <p>I.e. whether we arrived there via a copy 'request' (that is, an expression involving an lvalue source) or via a move request (an expression involving an rvalue source), we must have the same result regardless of what 'actually' happened (whether a copy special member or move special member was involved, if at all).</p> <p>Of interest is the fact that the traits such as <code>std::is_copy_constructible</code> used to be called <code>std::has_copy_constructor</code>, but were renamed to put the emphasis on expressions rather than intrinsic properties: something like <code>std::is_copy_constructible&lt;int&gt;::value &amp;&amp; std::is_move_assignable&lt;int&gt;::value</code> is true regardless of the fact that <code>int</code> has no constructors or assignment operators.</p> <p>I advise you to really do generic programming by expressing constraints on the expression level because e.g. the presence or absence of a move constructor is neither sufficient nor necessary for a type to be copy constructible.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
    1. This table or related slice is empty.
 

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