<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
   "http://www.w3.org/TR/html4/strict.dtd">

<html>
<head>

  <meta http-equiv="Content-Type" content="text/html;charset=US-ASCII">

<!-- This should replace the style block once it is published somewhere accessible
  <link href="../../base_www/style.hinc" rel="stylesheet" type="text/css" />
-->

  <style type="text/css">

    body { color: #000000; background-color: #FFFFFF; }
    del { text-decoration: line-through; color: #8B0040; }
    ins { text-decoration: underline; color: #005100; }

    p.example { margin-left: 2em; }
    pre.example { margin-left: 2em; }
    div.example { margin-left: 2em; }

    code.extract { background-color: #F5F6A2; }
    pre.extract { margin-left: 2em; background-color: #F5F6A2;
      border: 1px solid #E1E28E; }

    p.function { }
    .attribute { margin-left: 2em; }
    .attribute dt { float: left; font-style: italic;
      padding-right: 1ex; }
    .attribute dd { margin-left: 0em; }

    blockquote.std { color: #000000; background-color: #F1F1F1;
      border: 1px solid #D1D1D1;
      padding-left: 0.5em; padding-right: 0.5em; }
    blockquote.stddel { text-decoration: line-through;
      color: #000000; background-color: #FFEBFF;
      border: 1px solid #ECD7EC;
      padding-left: 0.5empadding-right: 0.5em; ; }

    blockquote.stdins { text-decoration: underline;
      color: #000000; background-color: #C8FFC8;
      border: 1px solid #B3EBB3; padding: 0.5em; }

    table { border: 1px solid black; border-spacing: 0px;
      margin-left: auto; margin-right: auto; }
    th { text-align: left; vertical-align: top;
      padding-left: 0.8em; border: none; }
    td { text-align: left; vertical-align: top;
      padding-left: 0.8em; border: none; }

    table.docinfo { border: none; border-spacing: 0px;
      margin-left: auto; margin-right: none; float: right; }

  </style>

  <title>Defaulted comparison operator semantics should be uniform</title>

</head>

<body>
  <table border="1" class="docinfo">
    <tr> <th>Doc. No.:</th> <td>N4401</td> </tr>
    <tr> <th>Date:</th>     <td>2015-04-07</td> </tr>
    <tr> <th>Project:</th>  <td>Programming Language C++, Evolution Working Group</td> </tr>
    <tr> <th>Reply To:</th> <td>Michael Price<br/>
                                &lt;<a href="mailto:michael.b.price.dev@gmail.com">michael.b.price.dev@gmail.com</a>&gt;</td> </tr>
  </table>

  <br/>
  <h1>Defaulted comparison operator semantics should be uniform</h1>

  <h2><a name="introduction">I. Introduction</a></h2>

  <p>
    Argues that WG21 should keep the semantics of any compiler-generated
    comparison operators uniform with those of other compiler-generated
    special member functions; specifically that <strong><code>mutable</code>
    and pointer members should be included in the default comparison
    operations</strong>.
  </p>

  <h2><a name="details">II. The Details</a></h2>

  <p>
    Given the following types and their relationships
  </p>

  <pre class="example">
  <code>struct Base {
      std::string name;
  };

  class Member {
      int value;
  };

  class MyType : public Base {
      mutable Member member;
      std::string * id;
  };</code>
  </pre>

  <p>
    We have existing rules that determine what happens during the constructor
    of an instance of <code>MyType</code>.
  </p>

  <p>
    Paragraph 12.6.2.13 [<a href="#ref_1">1</a>] reads:
  </p>

  <blockquote class="std"><p>
    In a non-delegating constructor, initialization proceeds in the following order:
    <br/>
    <div style="text-indent:-1em; margin-left:2em;">
      &mdash;First, and only for the constructor of the most derived class (1.8),
      virtual base classes are initialized in the order they appear on a
      depth-first left-to-right traversal of the directed acyclic graph of base
      classes, where "left-to-right" is the order of appearance of the base
      classes in the derived class <em>base-specifier-list,</em>
    </div>
    <br/>
    <div style="text-indent:-1em; margin-left:2em;">
      &mdash;Then, direct base classes are initialized in declaration order as they
      appear in the <em>base-specifier-list</em> (regardless of the order of the
      <em>mem-initializers</em>).
    </div>
    <br/>
    <div style="text-indent:-1em; margin-left:2em;">
      &mdash;Then, non-static data members are initialized in the order they
      were declared in the class definition (again regardless of the order of
      the <em>mem-initializers</em>).
    </div>
    <br/>
    <div style="text-indent:-1em; margin-left:2em;">
      &mdash;Finally, the <em>compound-statement</em> of the constructor body is
      executed.
    </div>
    <br/>
    <div>
      [<em>Note:</em> The declaration order is mandated to ensure that the base
      and member subobjects are destroyed in the reverse order of initialization.
      &mdash;<em>end note</em>]
    </div>
  </p></blockquote>

  <p>
    The ordering rules for implictly defined copy and move constructors (12.8.15)
    reference paragraph 12.6.2, and the ordering for implicity defined copy
    and move assignment operators (12.8.28) are similarly described.
  </p>

  <p>
    Paragraph 12.8.15 [<a href="#ref_1">1</a>] reads:
  </p>

  <blockquote class="std"><p>
    The implicitly-defined copy/move constructor for a non-union class
    <code>X</code> performs a memberwise copy/move of its bases and members.
    [<em>Note: brace-or-equal-initializers</em> of non-static dta members are
    ignored. See also the example in 12.6.2. &mdash;<em>end note</em>] The order
    of initialization is the same as the order of initialization of bases and
    members in a user-defined constructor (see 12.6.2). Let <code>x</code> be
    either the parameter of the constructor or, for the move constructor, an
    xvalue referring to the parameter. Each base or non-static data member is
    copied/moved in the manner appropriate to its type:
    <br/>
    <div style="text-indent:-1em; margin-left:2em;">
      &mdash;if the member is an array, each element is direct-initialized with
      the corresponding subobject of <code>x</code>;
    </div>
    <br/>
    <div style="text-indent:-1em; margin-left:2em;">
      &mdash;if a member <code>m</code> has rvalue reference type
      <code>T&amp;&amp;</code>, it is direct-initialized with
      <code>static_cast&lt;T&amp;&amp;&gt;(x.m)</code>;
    </div>
    <br/>
    <div style="text-indent:-1em; margin-left:2em;">
      &mdash;otherwise, the base or member is direct-initialized with the
      corresponding base or member <code>x</code>.
    </div>
    <br/>
    <div>
      Virtual base class subobjects shall be initialized only once by the
      implicitly-defined copymove constructor (see 12.6.2).
    </div>
  </p></blockquote>

  <p>
    Paragraph 12.8.28 [<a href="#ref_1">1</a>] reads:
  </p>

  <blockquote class="std"><p>
    The implicitly-defined copy/move assignment operator for a non-union class
    <code>X</code> performs memberwise copy/move assignment of its subobjects.
    The direct base classes of <code>X</code> are assigned first, in the order
    of their declaration in the <em>base-specifier-list</em>, and then the
    immediate non-static data members of <code>X</code> are assigned, in the
    order in which they were declared in the class definition. Let <code>x</code>
    be either the parameter of the function or, for the move operator, an xvalue
    referring to the parameter. Each subobject is asigne din the manner
    appropriate to its type:
    <br/>
    <div style="text-indent:-1em; margin-left:2em;">
      &mdash;if the subobject is of class type, as if by a call to
      <code>operator=</code> with the subobject as the object expression and the
      corresponding subobject of <code>x</code> as a single function argument
      (as if by explicity qualification; that is, ignoring any possible virtual
      overriding functions in more derived classes);
    </div>
    <br/>
    <div style="text-indent:-1em; margin-left:2em;">
      &mdash;if the subobject is an array, each element is assigned, in the
      manner appropriate to the element type;
    </div>
    <br/>
    <div style="text-indent:-1em; margin-left:2em;">
      &mdash;if the subobject is of scalar type, the built-in assignment
      operator is used.
    </div>
    <br/>
    <div>
      It is unspecified whether subobjects representing virtual base classes are
      assigned more than once by the implicitly-defined copy/move assignment
      operator.
    </div>
  </p></blockquote>

  <p>
    Tellingly, we have no special considerations for members that could possibly
    cause undesired behavior, particularly for <code>mutable</code> and pointer
    members.  We've left it to the designer of <code>MyType</code> to understand
    whether the generated special member functions satisfy the requirements for
    the type, and if they do not, they are free to implement the desired semantics.
  </p>

  <p>
    In N4175 [<a href="#ref_2">2</a>], it was argued that <code>mutable</code>
    and pointer members should be excluded from default-generated comparison
    operators. The general argument is that any generated comparison operators
    for those kinds of members might not be what a user expects; ordered
    comparisons for pointers currently have serious problems and comparing a
    <code>mutable</code> member could have side-effects on its value. Those
    concerns are valid, but that is our current state with regards to other
    generated special member functions. Therefore, the proposal to include
    those types in the default comparisons are likely to only be palatable if
    we agree to restrict the generation to those cases where we believe it
    should be a safe operation, or to impose stricter requirements, such as
    forcing the author to explicitly <em>opt-in</em> to the default behavior by
    requiring the author of a type to request the default implementation via
    <code>= default;</code>.
  </p>

  <p>
    Complicating the special member functions by ignoring components of an
    instance's value for a subset of those functions doesn't seem like the best
    path forward to this author.  Instead, we should not try to assume too much
    about the intention of the author of a class and trust that they understand
    that the use of "unusual" types as members requires doing extra work, as we
    have maintained for the past several decades.
  </p>

  <h2><a name="acknowledgements">III. Acknowledgements</a></h2>

  <p>
    Many thanks to my employer, Lexmark International, for continuing to support
    my work on the committee. Several of my co-workers, Andrew Regier, Chris
    Sammis, and Serhan Yengulalp, provided invaluable feedback on early drafts
    that led me to clarify my position and address previously ignored issues.
  </p>

  <h2><a name="references">IV. References</a></h2>

  <a name="ref_1" />
  <div>[1] <a href="http://www.open-std.org/jtc1/sc22/wg21/prot/14882fdis/n4140.pdf">R. Smith, <em>Working Draft, Standard for Programming Language C++</em>. N4140.</a></div>
  <a name="ref_2" />
  <div>[2] <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4175.pdf">B. Stroustrup, <em>Default Comparisons</em>. N4175.</a></div>

</body>
</html>
