﻿<!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=UTF-8">

<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; }

</style>

<title>Ruminations on relational operators</title>
</head>
<body>
<h1>Ruminations on relational operators</h1>

<p>
ISO/IEC JTC1 SC22 WG21 N3764 - 2013-09-02
</p>

<address>
Ville Voutilainen, ville.voutilainen@gmail.com
</address>

<h2><a name="Abstract">Abstract</a></h2>

<p>
This paper enumerates existing practice for relational operators,
enumerates various proposals for changing/fixing the relational
operators for std::optional, and proposes to apply a strategy
consistent with the relational operators of std::tuple.
</p>

<h2><a name="Existing_practice">Existing practice</a></h2>

<p>
There are various inconsistencies with the existing practice:
<ul>
<li>operator&lt; for pointers doesn't establish a total ordering,
but pointers have a specialization for std::less.</li>
<li>standard containers and tuple synthesize relational operators
in terms of operator&lt; even if the underlying type doesn't have
that operator, but they don't have specializations for std::less
for pointers.</li>
<li>std::optional has just operator== and operator&lt;, and
provides no std::less specialization, but rather invokes
std::less from optional's operator&lt;.</li>
<li>boost::optional synthesizes relational operators if the underlying
type doesn't have them. Boost also has <a href="http://www.boost.org/doc/libs/1_54_0/libs/utility/OptionalPointee.html#less">OptionalPointee</a> for certain generic programming cases.</li>
<li>boost::tuple puts the relational operators into a separate
header that the user has to include to use the operators, and
doesn't synthesize the operators if the underlying type doesn't
have them.</li>
</ul>
</p>

<h2><a name="optional_fuss">What's the fuss about optional?</a></h2>

<p>There was quite a lot of discussion about what the relational operators
of optional should do. The controversy arises between two views:
according to one, optional should be consistent with other types
in the standard. According to the other, optional should be as
transparent as possible, and as similar to its underlying type
as possible. The first view is quite straightforward, the operators
would be synthesized. The second view would allow optional to
work like types that eg. have no operator&gt;, in that case
optional wouldn't have that operator either. The second view
would also treat optional&lt;double&gt; the same way as raw double
as far as relational operators and NaNs are concerned.</p>

<h2><a name="for_synthesizing">Arguments for consistency and synthesizing</a></h2>

<p>
Stepanov has some interesting words to say about NaNs in
his paper <a href="http://www.stepanovpapers.com/notes.pdf">http://www.stepanovpapers.com/notes.pdf</a> (pages 24-25). The author of this paper doesn't
think optional should try to cater for NaNs or types that
define just a part of relational operators but not all of them.
Standard tuple and containers don't, their strategy is to
define operator&lt;, and then define all the other relational
operators in terms of operator&lt;. The author of this paper
finds being consistent a much stronger argument than the
perceived transparency of optional.
</p>

<h2><a name="against_synthesizing">Arguments for not synthesizing</a></h2>

<p>
It seems quite natural for many people to think of optional&lt;T&gt;
to be just a T with an additional value (nullopt). Hence it's according
to expectations that optional&lt;T&gt; would not have relational
operators that the underlying T doesn't have. Tony Van Eerd points
out that complex is an interesting example; it doesn't have operator&lt;,
but it has a specialization of std::less, so it would be awkward
if optional&lt;complex&lt;T&gt;&gt; has an operator&lt; but complex&lt;T&gt;
does not.
</p>

<h2><a name="why_no_operator_not_equal">Why didn't we get even operator!= for optional?</a></h2>

<p>
The author of this paper is mystified by the lack of operator!= for
optionals. As Marc Glisse pointed out, it works just fine even
for NaN doubles even if operator!= is defined as the boolean opposite
of operator==.
</p>

<h2><a name="synthesis">Have we achieved any synthesis?</a></h2>

<p>
It thus far seems that both the synthesis proponents and opponents
agree that optional should have std::less specializations, to make
optional&lt;T*&gt; and optional&lt;complex&lt;T&gt;&gt; work properly
with ordered associative containers. The remaining debate seems to be 
between synthesizing and not synthesizing. It seems to the author
of this paper that std::complex is not an issue; the synthesized
operators would all be ill-formed since operator&lt; is, and the
rest would be defined in terms of operator&lt;. It also seems
that both camps are beginning to agree that optional's relational
operators should not use std::less (mostly because of the case
with complex) but should invoke the underlying type's relational
operators. The synthesis would give an operator&gt; for an
optional&lt;T&gt; even if T has just operator&lt;, the non-synthesis
wouldn't.
</p>

<h2><a name="author_proposal">Author's proposal</a></h2>

<p>
This paper proposes to make optional's relational operators
do the same thing that tuple and containers do, aka synthesize
the operators without using std::less, and in addition to that, 
add std::less specializations for containers/tuples/optionals holding 
pointers or std::complex. If the National Body of the author has
done its job, there are NB comments on the C++14 CD requesting
the same (although they probably don't take complex into account).
Daniel Krügler has proposed that such specialization 
should be written as variadic templates, so that we wouldn't need to specialize
just for pointers, roughly like
<code>
less&lt;tuple&lt;T...&gt;&gt;
</code>
, which would also work for complex and nested tuples of tuples of vectors
of optionals, when all of these have a proper less specialization.
</p>
</body>
</html>
