﻿<html>

<head>
    <meta http-equiv="Content-Language" content="en-us">
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>Explicitly defaulted comparison operators</title>
    <style type="text/css">
        body {
            font-size: 11pt;
            font-family: Verdana, Sans-Serif;
        }
        p {
        }
        blockquote {
            border: solid thin;
            padding: 1em 1em 1em 1em;
        }

        blockquote.stdins {
            background-color: #CEFFCE;
        }

        blockquote.std {
            background-color: #E5E5E7;
        }

        ins {
            color: #005100;
        }

        li {
            padding-bottom: 0.3em;
        }

        pre {
            background-color: #F7F6dc;
            margin-left: 3em;
            margin-right: 3em;
            padding: 1em 1em 1em 1em;
            font-size: 90%;
        }
    </style>
</head>

<body>

  <table border="0" cellpadding="0" cellspacing="0" style="border-collapse: collapse" bordercolor="#111111" width="619">
    <tr>
      <td width="167" align="left" valign="top">Document number:</td>
      <td width="452">N4126</td>
    <tr>
      <td width="167" align="left" valign="top">Date:</td>
      <td width="452">2014-07-29</td>
    </tr>
    <tr>
      <td width="167" align="left" valign="top">Project:</td>
      <td width="452">Programming Language C++, Language Evolution Working Group</td>
    </tr>
    <tr>
      <td width="167" align="left" valign="top">Reply-to:</td>
      <td width="452">Oleg Smolsky 
        &lt;<a href="mailto:oleg.smolsky@gmail.com">oleg.smolsky@gmail.com</a>&gt;
      </td>
    </tr>
  </table>

    <h1>Explicitly defaulted comparison operators</h1>

    <h2>Revision history</h2>
        <p><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n3950.html">N3950</a>
        was presented to the Evolution WG at the Rapperswil meeting and the response was very
        positive.
        A later revision, 
        <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4114.htm">N4114</a>
        was amended to handle the following points requested at the meeting:
        <ul>
        <li>Support for non-member operators
        <li>Mutable members: there was consensus on their treatment. The compromise is to
            to make explicitly defaulted operators ill-formed when mutable members are present.
            See <a href="#mutable">"Mutable members"</a>.
        <li>Short-hand notation was proposed and had very positive feedback.
            See <a href="#shorthand">"The proposed syntax: short form"</a>.
        </ul>

        <p>This proposal makes the following changes after the technical review on 
        the <i>c++std-ext</i> list:
        <ul>
        <li>Pointer, floating point and enumerated type members are included.
            See <a href="#thedomain">"Domain of the operator functions"</a> for the discussion.
        <li>Each explicitly defaulted operator is independent and is bridged to the respective
            members' operators
        <li>Lexicographical comparison is defined explicitly
        </ul>

    <h2>I. Introduction</h2>
    <p>Equality for composite types is an age-old problem which effects an overwhelming chunk
       of the programming community. Specifically, the users that program with
       <i>Regular</i><sup><a href="#regular">1</a></sup> types and 
       expect that they would compose naturally.

    <p>The proposal presents means of generating default equality/inequality for <i>Regular</i>, as well
       as relational operators for <i>Totally Ordered</i><sup><a href="#totallyordered">2</a></sup>
       user-defined types. Such types should 
       be trivial to implement and easy to understand. 

    <p>Specifically, I argue that:
    <ol>
    <li>The presence of <code>operator==()</code> implies that the
       type is Regular. I expect that the equality is defined to return <code>true</code> IFF both
       objects represent the same value (this relation is transitive, reflexive and symmetric) 

    <li>The presence of <code>operator&lt;()</code> implies that the type is Totally Ordered.
    </ol>

    <p>Finally, the feature is strictly "opt in" so that semantics of existing code remain intact.

    <h2>II. Motivation and scope</h2>

    <p>Simple means of doing equality are really
       useful in modern C++ code that operates with types
       composed of Regular members. The definition of equality is trivial in such cases -
       member-wise comparison. Inequality should then be generated as its boolean negation.

    <p>This proposal focuses on Regular and Totally Ordered types as they naturally compose. Such
       cases are becoming more prevalent as people program more with value types and so writing
       the same equality and relational operators becomes tiresome. This is especially true when 
       trying to lexicographically compare members to achieve total ordering.

    <p>Consider the following trivial example where a C++ type represents some kind of
        user record:

        <pre>
struct user
{
    uint32_t id, rank, position;

    std::string first_name, last_name;

    std::string address1, address2, city, state, country;
    uint32_t us_zip_code;

    friend bool operator==(const user &amp;, const user &amp;);
    friend bool operator!=(const user &amp;, const user &amp;);

    friend bool operator&lt;(const user &amp;, const user &amp;);
    friend bool operator&gt;=(const user &amp;, const user &amp;);
    friend bool operator&gt;(const user &amp;, const user &amp;);
    friend bool operator&lt;=(const user &amp;, const user &amp;);
};</pre>

        <h3>Verbosity</h3>
        The structure consists of regular members and the implementation of the equality operator 
        is trivial yet verbose:

        <pre>
bool operator==(const user &amp;a, const user &amp;b)
{
    <b>return</b> a.id == b.id &amp;&amp;
           a.rank == b.rank &amp;&amp;
           a.position == b.position &amp;&amp;
           a.address1 == b.address1 &amp;&amp;
           a.address2 == b.address2 &amp;&amp;
           a.city == b.city &amp;&amp;
           a.state == b.state &amp;&amp;
           a.country == b.country &amp;&amp;
           a.us_zip_code == b.us_zip_code;
}</pre>

<p>Also, the composite type is naturally Totally Ordered, yet that takes even more code:
<pre>
bool operator&lt;(const user &amp;a, const user &amp;b)
{
    <i style="color: green;">// I could implement the full lexicographical comparison of members manually, yet I 
    // choose to cheat by using standard libraries</i>
    <b>return</b> std::tie(a.id, a.rank, a.position,
                    a.address1, a.address2, a.city, a.state, a.country, 
                    a.us_zip_code)
           &lt;
           std::tie(b.id, b.rank, b.position, 
                    b.address1, b.address2, b.city, b.state, b.country,
                    b.us_zip_code);
}</pre>

        Specifically, this code, while technically required, suffers from the following issues:
        <ul>
        <li>needlessly verbose - every member is already comparable (Regular and Totally Ordered)
        <li>error prone - the author could miss a member and  the implementation may become stale 
            when a new member is added
        <li>not in the spirit of Modern C++: correct things should be intuitive and easy
        </ul>

        <h3>Correctness</h3>

        <p>It is vital that equal/unequal, less/more-or-equals and more/less-or-equal pairs
        behave as boolean negations of each other. After all, we are building total ordering
        and the world would make no sense
        if both <code>operator==()</code> and <code>operator!=()</code> returned <i>false</i>!
        
        <p>As such, it is common to implement these operators in terms of each other.

        <p>Inequality for Regular types:

        <pre>
bool operator!=(const user &amp;a, const user &amp;b) 
{
    return !(a == b);
}</pre>

        <p>Relational operators for Totally Ordered types:
<pre>
bool operator&gt;=(const user &amp;a, const user &amp;b)
{
    return !(a &lt; b);
}

bool operator&gt;(const user &amp;a, const user &amp;b)
{
    return b &lt; a;
}

bool operator&lt;=(const user &amp;a, const user &amp;b)
{
    return !(a &gt; b);
}</pre>

        Notes:
        <ul>
        <li>Based on my experience, these templates are applicable to the vast
            majority of user-defined types that aggregate Regular members
        <li>The users should have some kind of "short hand" for stating what is common, 
            correct and simple
        <li>These relations are algebraic in nature and must be considered carefully.
            For example,
            <code>operator&lt;()</code> must remain transitive in its nature,
            <code>operator==()</code> is supposed to be symmetric, reflexive and transitive.
        </ul>



    <h2>III. The syntax</h2>
    <h3>The proposed syntax: long form</h3>
        <p>Member-wise generation of special functions is already present in the Standard 
        (see Section 12), so it seems natural to extend the scope of generation and reuse
        the existing syntax.

        <p>The proposed syntax for generating the new explicitly defaulted non-member
           operators is as follows:
    <pre class="code">
struct Thing
{
    int a, b, c;
    std::string d;
};

bool operator==(const Thing &amp;, const Thing &amp;)<b>= default</b>;
bool operator!=(const Thing &amp;, const Thing &amp;)<b>= default</b>;
</pre>

    <p>There are cases where members are private and so the operators need to be declared as
    <b>friend</b>. Consider the following syntax:
    <pre class="code">
class AnotherThing
{
    int a, b;

public:
    <i style="color: green;">// ...</i>

    <b>friend</b> bool operator&lt;(Thing, Thing)<b> = default</b>;
    <b>friend</b> bool operator&gt;(Thing, Thing)<b> = default</b>;
    <b>friend</b> bool operator&lt;=(Thing, Thing)<b> = default</b>;
    <b>friend</b> bool operator&gt;=(Thing, Thing)<b> = default</b>;
};
</pre>

<p>I feel this is a natural choice because:
       <ul>
            <li>C++11 already has member function specifiers such as <b>default</b> and 
                <b>delete</b>
            <li>Users can "opt in" to get the new behavior, thus the behavior of the existing
                code is unchanged
            <li>The new functions are explicitly declared using a familiar syntax, so users
                get a feel of what they are asking for
            <li>The user can specify whether the parameters are taken by value or by reference
       </ul>

    <a name="shorthand">
    <h3>The proposed syntax: short form</h3></a>
        <p>Several committee members expressed a strong desire for a shorter
           form of notation that would radically reduce the amount of code it takes
           to declare the non-member operators. Here is the short-hand that
           extends to the long form defined above.

        <pre class="code">
struct Thing
{
    int a, b, c;
    std::string d;

    default: ==, !=, &lt;, &gt;, &lt;=, &gt;=;<i style="color: green;">   // defines the six non-member functions</i>
};</pre>
    
    <p>Notes: 
       <ul>
            <li>Radical reduction in boiler-plate that must otherwise get copied and pasted
            <li>The compiler will choose how to pass the arguments in order to achieve the best 
                performance
       </ul>

    <h2>IV. Design decisions and discussion</h2>

    <h3>A library-only solution</h3>
    <p>It is possible to write a templated "CRTP" base class that implements equality 
    and relational operators. For an example, see Boost.Operators.

    <p>Comment from Nevin Liber: <i>I believe this breaks standard layout if you use private derivation (and it is unlikely that we will want public derivation, given the deprecation of things like unary_function and binary_function).</i></p>

    <p>Other committee members mentioned "upcoming, to be specified" reflection facilities
       yet, I feel, a first-class language feature is needed now.<p>

    <a name="mutable">
    <h3>Mutable members</h3></a>
    <p>The Evolution WG was divided on the <code>mutable</code> treatment. There were
       two mutually exclusive views:
        <ol>
        <li>Exclude <code>mutable</code> members from the comparison operators.<br>
            - such members were invented for caching data derived from the object's state<br>
            - as such, they are not a part of the value type and should not participate in comparisons
        <li>Include <code>mutable</code> members when doing comparisons (ie no special treatment)<br>
            - such implementation is consistent with special member functions: copy constructor and assignment operator
        </ol>

    <p>I prefer option (1) above, yet the only way to resolve the committee dead lock is to make
       code with such members ill-formed. The user would have to implement the comparison operators
       manually. The committee thus reserves an option to reconsider the decision at a later stage,
       as part of a follow up proposal.</p>

    <h3>Single member types</h3>
    <p>The feedback on the <code>c++std-ext</code> list included the "single member wrapper struct" 
       case where the author expects every overloaded operator of the wrapper to work consistently
       to those of the member.

    <p>Consider the following user-defined type:<pre class="code">
struct wrapper
{
    double val;
    
    default: ==, !=, &lt;, &gt;, &lt;=, &gt;=;<i style="color: green;">   // defines the six non-member functions</i>
};</pre>
    
    Such a thing would be built from a <code>double</code> and it makes sense to build
    the equality and relational operators based on the member's operators. This treatment
    covers every possible case: total order, strict weak order and even partial order
    (as the ambiguities in the last case are simply bridged to the caller).

    <p>Namely,
    <pre>
bool operator==(const wrapper &amp;a, const wrapper &amp;b) 
{
    return a.val == b.val;
}

bool operator!=(const wrapper &amp;a, const wrapper &amp;b) 
{
    return a.val != b.val;
}

bool operator&lt;(const wrapper &amp;a, const wrapper &amp;b) 
{
    return a.val &lt; b.val;
}

bool operator&lt;=(const wrapper &amp;a, const wrapper &amp;b) 
{
    return a.val &lt;= b.val;
}

bool operator&gt;(const wrapper &amp;a, const wrapper &amp;b) 
{
    return a.val &gt; b.val;
}

bool operator&gt;=(const wrapper &amp;a, const wrapper &amp;b) 
{
    return a.val &gt;= b.val;
}</pre>

    <h3>Multi-member types</h3>
    <p>The original usecase for the proposal revolves around user-defined types that 
       contain many regular members. These types must receive memberwise implementations
       of <code>operator==()</code> and <code>operator&lt;()</code> and the other
       operators may be derived.

    <p>Namely, consider the shortest implementation of <code>operator&gt;=()</code>:
      <pre>
bool operator&gt;=(const thing &amp;t1, const thing &amp;t2)
{
    return !(a &lt; b);
}
</pre>
    <p>Notes on this option:
    <ul>
      <li>It is consistent with <code>std::pair</code> and <code>std::tuple</code>
      <li>It is inconsistent with the aforementioned single-member case and may
          surprise people who deal with partial orders
      <li>There is an implicit dependency on <code>operator&lt;()</code>
    </ul>

    <p><b>Conclusion:</b> the most consistent and straightforward option is to follow
       the dominating single-member case and generate each explicitly defaulted operator
       fully.

    <h3>Efficiency of the lexicographical comparison</h3>
    Consider the following user-defined type:
    <pre>
struct thing
{
   int a, b, c;
};</pre>
       
       <p><b>Option 1:</b> use the members' strict weak order to implement 
       <code>operator&lt;()</code>. 
       This is consistent with <code>std::pair</code> and <code>std::tuple</code>.
        <pre>
bool operator&lt;(const thing &amp;t1, const thing &amp;t2) 
{
    if (t1.a &lt; t2.a) return true;
    if (t2.a &lt; t1.a) return false;
    if (t1.b &lt; t2.b) return true;
    if (t2.b &lt; t1.b) return false;

    return t1.c &lt; t2.c;
}
</pre>       

    <p><b>Option 2:</b> use the members' total order to implement <code>operator&lt;()</code>.
       This puts an implicit dependency on <code>operator==()</code>.
        <pre>
bool operator&lt;(const thing &amp;t1, const thing &amp;t2) 
{
    if (t1.a != t2.a)
        return t1.a &lt; t2.a;
    if (t1.b != t2.b)
        return t1.b &lt; t2.b;
    
    return t1.c &lt; t2.c;
}
</pre>
  </p>

    <a name="thedomain">
    <h3>Domain of the operator functions</h3></a>
    <p>There are some built-in types that are not totally ordered or cannot always 
       be compared. Namely, <code>&lt;</code> is only defined for pointers of the same type 
       that refer to memory allocated from a single contiguous region, IEEE floating 
       point numbers have the NaN value and the comparisons are defined in a very special way.

    <p>Design decisions:
    <ol>
        <li>Integral types, enumerated types, pointer types and floating point types
            are supported
        <li>The generated operators are only defined in the domain of the members' normal
            values
    </ol>

    <h2>V. Technical specifications</h2>
    <h3>Edit section 8.4.2 "Explicitly-defaulted functions [dcl.fct.def.default]" </h3>

    <ol>
    <li><blockquote class="std">A function definition of the form:<br>
        <i>attribute-specifier-seq<sub>opt</sub> decl-specifier-seq<sub>opt</sub> declarator virt-specifier-seq<sub>opt</sub></i> = <b>default</b> ;<br>
        is called an explicitly-defaulted definition. A function that is explicitly defaulted shall<br>
        — be a special member function<ins>, or an explicitly defaultable operator
       function. See [defaultable]</ins></blockquote>
    </ol>

    <h3>New section in 8.4</h3>

    <p>After 8.4.3 add a new section
    <blockquote class="stdins">
    <b>8.4.4 Explicitly defaultable operator functions [defaultable]</b>
    <p>The following friend operator functions are explicitly defaultable:
        <ol>
        <li>Non-member equality operators: 
            <code>operator==()</code>, <code>operator!=()</code>, see [class.equality]
        <li>Non-member relational operators: 
            <code>operator&lt;()</code>, <code>operator&gt;()</code>,
            <code>operator&lt;=()</code>, <code>operator&gt;=()</code>, see [class.relational]
        </ol>
    </blockquote>

    <h3>Edit section "12 Special member function [special]" </h3>
    <p><blockquote class="std">The default constructor (12.1), copy constructor and copy assignment operator (12.8), 
        move constructor and move assignment operator (12.8) and destructor (12.4) are special
        member functions. 
        <ins>These, together with equality operators (12.10) and
        relational operators (12.11) may be explicitly defaulted as per 
        [dcl.fct.def.default]</ins></blockquote>

    <h3>New sections in 12</h3>

    <p>After 12.9 add a new section
    <blockquote class="stdins">
    <p><b>12.10 Equality operators [class.equality]</b>
    <ol>
        <li>A class may provide overloaded <code>operator==()</code> and 
            <code>operator!=()</code> as per [over.oper].
            A default implementation of these non-member operators may be
            generated via the <code>= default</code> notation as it may be explicitly
            defaulted as per [dcl.fct.def.default].

        <li>The defaulted <code>operator==()</code> definition is generated if and only if all 
            sub-objects are fundamental types or compound types thereof, that provide operator==().

        <li>If a class with a defaulted <code>operator==()</code> has a <code>mutable</code>
            member, the program is ill-formed

        <li>The defaulted <code>operator==()</code> for class X shall take two arguments
            of type X by value or by const reference and return bool.

        <li>The explicitly defaulted non-member <code>operator==()</code> for a class X
            shall perform memberwise equality comparison of its subobjects. 
            Namely, a comparison of the subobjects that have the same position in both objects
            against each other until one subobject is not equal to the other.

            <p>Direct base classes of X are compared first, in the order of their declaration in the 
            base-specifier-list, and then the immediate non-static data members of X are compared,
            in the order in which they were declared in the class definition.

            <p>Let x and y be the parameters of the defaulted operator function. Each subobject
            is compared in the manner appropriate to its type:

            <ul>
                <li>if the subobject is of class type, as if by a call to <code>operator==()</code> with
                    the subobject of x and the corresponding subobject of y as a
                    function arguments (as if by explicit qualification; that is, ignoring any 
                    possible virtual overriding functions in more derived classes);

                <li>if the subobject is an array, each element is compared in the manner appropriate 
                    to the element type;

                <li>if the subobject is of a scalar type, the built-in <code>==</code> operator is used.
            </ul>

        <li>The explicitly-defaulted non-member <code>operator!=()</code> for a non-union 
            class shall be implemented in a manner described in (5) while calling
            <code>operator!=()</code> and the built-in <code>!=</code> operator where 
            appropriate.
    </ol>

    <p>Example: <pre>struct T {
    int a, b, c;
    std::string d;
};

bool operator==(const T &amp;, const T &amp;) = default;</pre>

    <p>Note, floating point values are regular only in the domain of normal values
       (outside of the NaN) and so the explicitly-defaulted non-member operators
       are only defined in that domain too.</p>
       
</blockquote>


    <p>After 12.10 add a new section
    <blockquote class="stdins">
    <b>12.11 Relational operators [class.relational]</b>
    <ol>
        <li>A class may provide overloaded relational operators as per [over.oper]. 
            A default implementation of a non-member relational operator may be generated
            via the <code>= default</code> notation as these may be explicitly defaulted
            as per [dcl.fct.def.default].

        <li>The defaulted <code>operator&lt;()</code> definition is generated if and only if all 
            sub-objects are fundamental types or compound types thereof, that provide operator&lt;().

        <li>If a class with a defaulted <code>operator&lt;()</code> has a <code>mutable</code>
            member, the program is ill-formed

        <li>The defaulted <code>operator&lt;()</code> for class X shall take two arguments 
            of type X by value or by const reference and return bool.

        <li>The explicitly-defaulted <code>operator&lt;()</code> for a class X shall
            perform memberwise lexicographical comparison of its subobjects. Namely,
            a comparison of the subobjects that have the same position in both objects against each
            other until one subobject is not equivalent to the other. The result of comparing these
            first non-matching elements is the result of the function.

            <p>Direct base classes of X are compared first, in the order of their declaration in the 
            base-specifier-list, and then the immediate non-static data members of X are compared,
            in the order in which they were declared in the class definition.

            <p>Let x and y be the parameters of the defaulted operator function. Each subobject 
            is compared in the manner appropriate to its type:

            <ul>
                <li>if the subobject is of class type, as if by a call to <code>operator&lt;()</code> with
                    the subobject of x and the corresponding subobject of y as a
                    function arguments (as if by explicit qualification; that is, ignoring any 
                    possible virtual overriding functions in more derived classes);

                <li>if the subobject is an array, each element is compared in the manner appropriate 
                    to the element type;

                <li>if the subobject is of a scalar type, the built-in <code>&lt;</code> operator is used.
            </ul>

        <li>An explicitly-defaulted non-member <code>operator&gt;()</code> for a non-union
            class shall be implemented in a manner described in (5) while calling
            <code>operator&gt;()</code> and the built-in <code>&gt;</code> operator where 
            appropriate.

        <li>An explicitly-defaulted non-member <code>operator&gt;=()</code> for a non-union
            class shall be implemented in a manner described in (5) while calling
            <code>operator&gt;=()</code> and the built-in <code>&gt;=</code> operator where 
            appropriate.        

        <li>An explicitly-defaulted non-member <code>operator&lt;=()</code> for a non-union
            class shall be implemented in a manner described in (5) while calling
            <code>operator&lt;=()</code> and the built-in <code>&lt;=</code> operator where 
            appropriate.
    </ol>

    <p>Example: <pre>struct T {
    int a, b;

    friend bool operator&lt;(T, T) = default;
};</pre>

    <p>Note, pointer comparisons are only defined for a subset of values, floating point 
       values are totally ordered only in the domain of normal values (outside of the NaN), 
       so the explicitly-defaulted non-member operators are only defined in the domain 
       of members' normal values.
    </blockquote>

    <p>After 12.11 add a new section
    <blockquote class="stdins">
    <b>12.12 Explicitly defaulted equality and relational operators - short form [class.oper-short]</b>
    <ol>
        <li>A class may provide explicitly defaulted equality and relational
            operators as per [class.equality] and [class.relational] respectively. 
            These non-member operators can also be generated via the short form of
            the notation:<br>
            <code>default: [the coma-separated list of operators];</code>
        <li>The following six short-hand names map to the explicitly defaultable
            equality and relational operators: <code>==, !=, &lt;, &lt;=, &gt;, &gt;=</code>.
        <li>The implementation must expand each term of the short form into a full
            declaration subject to [class.equality] and [class.relational], while
            choosing how to pass the arguments in order to maximize performance.
    </ol>

    <p>Example:
    <pre class="code">
struct Thing
{
    int a, b, c;
    std::string d;

    default: ==, !=;<i style="color: green;">   // defines equality/inequality non-member functions</i>
};</pre>
    </blockquote>

    <h2>VI. Acknowledgments</h2>
        <p>I believe the fundamental idea comes from Alex Stepanov and his 
        work<sup><a href="#stepanov">3</a></sup> on <i>regular</i> types. These types are generalizations of the built-in types, so they need to support copying, assignment, and comparison. The C++ language has natively supported the first two points 
        from the beginning and this proposal attempts to address the last one.

        <p>I want to thank Andrew Sutton for the early feedback and guidance, as well as
           Bjarne Stroustrup for loudly asking for consensus on small, fundamental
           language cleanups that strive to make users' lives easier.

        <p>Editorial credits go to Daniel Krügler, Ville Voutilainen, Jens Maurer 
           and Lawrence Crowl - 
           thank you for helping with the technical specification!

        <p>Finally, many folks on the <code>c++std-ext</code> list have provided valuable 
           advice and guidance. Thank you for the lively discussion and your help with 
           steering the design!

    <h2>VII. References</h2>
    <ol>
    <li><a name="regular">The <i>Regular</i> concept is defined by Stepanov in the 
    following way:</a>
    <ul>
    <li>Default construction, destruction,  copy construction and assignment are defined
    <li>Copy and assignment are implemented fully (a copy is equal to the original)
    <li>Equality is defined to return <i>true</i> IFF both objects represent the same value
        (this relation is transitive, reflexive and symmetric) 
    <li>Inequality is defined as a boolean negation of equality
    </ul>

    <li><a name="totallyordered">The <i>Totally Ordered</i> concept extends <i>Regular</i>
    with the following:</a>
    <ul>
    <li><code>operator&lt;()</code> is defined, <code>operator&gt;=()</code> 
        is defined as its boolean negation
    <li>Every relational operator is transitive
    </ul>

    <li><a name="stepanov">Dehnert, James C. and Alexander A. Stepanov.</a> "Fundamentals of generic programming." In Generic Programming, International Seminar on Generic Programming, Dagstuhl Castle, Germany, April/May 1998. Selected Papers, eds. Mehdi Jazayeri, Rüdiger G. K. Loos, and David R. Musser, vol. 1766 of Lecture Notes in Computer Science, pages 1-11. Springer, 2000.
    <br>See <a href="http://www.stepanovpapers.com/DeSt98.pdf">http://www.stepanovpapers.com/DeSt98.pdf</a>
    </ol>

    <p>See <a href="http://www.elementsofprogramming.com/">"Elements of programming"</a>
       by Alexander Stepanov and Paul McJones for a full treatment of 
       <i>Regular</i> and <i>Totally Ordered</i> concepts.
</body>
</html>
