<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
  <meta http-equiv="content-type" content="text/html; charset=windows-1250">
  <title>Dxxxx constexpr in the libray</title>
  <style type="text/css">
    p {text-align:justify}
    li {text-align:justify}
    ins {background-color:#FFFF99}
    del {background-color:#FF9999}
  </style>
  </head>
  <body>
    <address>
      Document number: N2994=09-0184<br />
      <br />
      <a href="mailto:public@alisdairm.net">Alisdair Meredith</a><br />
      2009-10-23
    </address>

    <hr />

<h1>N2994 constexpr in the libray: take 2</h1>

<h2>Revisions</h2>
<p>
The following changes were made in response to LWG review:
<li>Removed support for duration arithmetic pending constexpr support for
    referefences to const</li>
<li>Removed changes to auto_ptr as we do not want to touch this deprecated class
</li>
<li>Struck constexpr from all copy constructors following feedback from core.
This is implied by = default as long as the constuctor is trivial.</li>
</p>

<h2>Motivation for paper</h2>
<p>
As more understanding is gained on the usage of new language features, a number
of library issues have been opened requesting better support for static
initialization of library types.  In some cases this is important (mutex
initialization) and in others it is merely convenient (e.g. sentinel iterators.)
Rather than simply tackle each existing issue and wait for further issues to be
opened, this paper conducts a review of each library clause to determine where
additional constexpr constructors are appropriate, and provides full wording for
those cases.  This has then been cross-referenced to the current issues list to
provide guidance on which issues might be considered resolved by this paper.
</p>
<p>
In a couple of cases, notably pair and tuple, this paper takes a broader look at
a number of related concerns in the area of initialization to be sure the issue
can be seen as completely resolved, rather than partially addressed.
</p>
<p>
A second motivation is that a number of Library issues have been reported around
the use of constexpr, especially for constructors.  Rather than discuss such
issues individually as they occur in sequence issue, it will be simpler to
collect such issues together and resolve questions on constexpr in a single
discussion.  As such, this paper addresses many LWG issues but does not directly
address many NB comments on the first CD ballot. As such any discussion on this
paper should probably be scheduled after NB comments are reviewed, but hopefully
not postponed until after the next CD.
</p>
<p>
This paper aims to resolve each of the following issues:

<li>801 - Open</li>
<li>827 - Open</li>
<li>828 - Review</li>
<li>1019 - Tentatively Read</li>
<li>1116 - New</li>
<li>1117 - New</li>
<li>1122 - New</li>
<li>1129 - New</li>
<li>1171 - New (only partially solved)</li>
</p>
<p>
Discussion on the following issue is deferred to a more specialized paper
<li>1156 - New</li>
</p>


<h2>Broad concerns</h2>
<p>
Static initialization is generally a good and valuable property when it is 
'free'.  Notably, static initialization is guaranteed thread-safe (whatever the
definition) and provides an initialization appropriate for burning into ROMs.
There are many library types where requiring constexpr constructors has little
impact on the expected implementation so are whole-heartedly recommended.
</p>
<p>
There is another broad category of types where constexpr constructors are
supportable, but do constrain the typical implementation.  A good example would
be vector, or any of the standard containers.  It is quite possible to support a
constexpr default constructor for empty containers by storing a null pointer to
the dynamic storage for the data structure.  However, this has an impact on many
container members to now explicitly check for the empty case and branch
appropriately.  While it would be convenient for any implementations already
supplied along these lines to support constexpr, it should certainly not be a
required implementation technique as there are many trade-offs involved in
picking the appropriate data structure and default state, most of which dominate
the motivation for static initialization in a few special cases.  Thus, the
recommendation is that no container type in clause 23 (with the possible
exception of array) should require constexpr constructors.
</p>
<p>
A similar argument might be made for basic_string or any library type with
implied dynamic storage.  However, it should be noted that the removal of
reference counting support from basic_string and implied transition to 'short
string optimization' would provide a default constructor that typically could
be declared constexpr.  Due to broad similarity with clause 23 containers this
paper does not make that recommendation, but it could well be worth discussing
further during any paper reivew.
</p>

<h2>Benefits of constexpr</h2>
<p>
constexpt functions are evaluated at translation time if the are called with
constant expressions - typically a literal as an argument, or the result of a
evaluating another constexpr function.  This is often a more familiar model than
using template metaprogramming to achieve the same effect, and should be
actively enabled in the library where possible.
</p>
<p>
However, the most important aspect of constexpr to the library today is the
notion of literal types and constexpr constructors.  A type is a literal type
all its members are literal types and it has at least one constexpr constructor.
The key advantage of literal types is that literal values can be created which
must be constant-initialized before main.  Constant initialization is stronger
guarantee than dynamic initialization, as the value does not not depend on
executing runtime code and so is suitable for burning to ROMs.  Likewise there
are no order-of-initialization concerns and the values can be safely shared in
multiple threads without inducing data races.
</p>

<h2>Limitations of constexpr</h2>
<p>
The constexpr feature contains some valuable support for use in templates, and
so generic code, but also some unfortunate limitations.
</p>
<p>
If a function is declared constexpr, it is limited to a special form and also
places requirements on its argument types.  Notably, arguments to a constexpr
function must be literal types.  In the case of a function template this is
relaxed a little, as there is no way to know at template parse time whether or
not it will be instantiated with literal types.  Rather than create an implied
requirement that all arguments are literal (or else the instantiation is
ill-formed) the semantics are that if a function template is declared constexpr,
the keyword is ignored at instantiation time if the arguments turn out not to be
literal types.  i.e constexpr is honoured if but only if it can be supported.
</p>
<p>
The first serious problem for generic code is that constexpr functions must pass
their arguments *by value*.  For this reason there are special rules governing
constexpr copy constructors.  However, in generic code the common idiom is to
pass by const reference to avoid a potentially expensive copy of an unknown
(until instantiation) type.  Broader support for constexpr through the library
would probably require a relaxing of the core feature restriction here, and
there is a French NB comment exactly that (xref to be supplied.)  The LWG may
consider sending a message in support of that request to Core, if we believe
such a facility is important and something they would use.  This paper does not
assume any outcome from that process.
</p>
<p>
Another restriction on literal types is that while they may perform all their
computations at compile time, that alone is not enough to support use as
non-type template parameters.  That was a part of the original feature design,
but did not survive the review process to the CD.  There is another French NB
comment in this regard (xref to be supplied.)  Again, LWG may want to consider
how this would affect the standard library and send a message to Core regarding
their expected use (or not) of such a feature.
</p>
<p>
Finally, constexpr functions are limited to either a function body with a single
return statement, or a constructor with an empty function body (that initializes
all non-static data members.)  This does not raise any undue concerns for this
paper.
</p>

<h2>Missing applications of constexpr</h2>
<p>
One library paper has already been applied as part of the initial constexpr
proposal.  This paper goes further and reviews all library classes for missed
opportunities to support literal values.  In many cases this is simply
supporting a null value for a type (such as a null shared_ptr) which may seem a
small gain, but is still valuable for creating efficient race-free initial
states for programs.
</p>

<h2>Mis-applications of constexpr</h2>
<p>
Certainly not every library type should support a constexpr constructor, either
because it would be meaningless, or would be too constraining on the implementation.
In this paper we deliberately do <b>not</b> apply constexpr to the following
components:
<ul>
<li>basic_string</li>
<li>containers</li>
<li>insert iterators</li>
<li>reverse/move iterator</li>
<li>regular expressions</li>
<li>exception classes</li>
<li>iostreams (other than end iterators)</li>
<li>threads</li>
<li>futures</li>
<li>locks</li>
<li>locales</li>
<li>function binders</li>
</ul>
</p>
<h2>Deferred applications of constexpr</h2>
<p>
There are a small number of special purpose libraries that remain beyond the
scope of this paper.  The following may yet benefit from constexpr in the future.
<ul>
<li>bitmask types</li>
<li>random number engines</li>
<li>random number distributions</li>
<li>atomic types</li>
</ul>
</p>

<p>
The following empty types are typically used for their static properties, so
while there is no reason they could not be made into literal types, there is
not much motivation either.  It might be interesting if at the core language
level such empty types (with implicit and trivial special members) implicitly
satisfied the constraints for a literal type.
<ul>
<li>type_traits</li>
<li>numeric_limits</li>
</ul>
</p>

<h2>Proposed Solution</h2>
<p>
This paper proposed we add constexpr default constructors for the following
library classes.
<ul>
<li>pair</li>
<li>tuple</li>
<li>unique_ptr</li>
<li>shared_ptr</li>
<li>weak_ptr</li>
<li>enable_shared_from_this</li>
<li>auto_ptr</li>
<li>mutex</li>
<li>istream_iterator</li>
<li>istreambuf_iterator</li>
<li>duration</li>
</ul>
</p>
<p>
Likewise, we should support constexpr operations on literal values of types that
can support them.
<ul>
<li>pair</li>
<li>tuple</li>
<li>duaration</li>
</ul>
However, this support is deferred to a later paper, pending core language
support for constexpr function (templates) that can accept arguments and return
results as reference-to-const.
</p>

<h2>Proposed Wording</h2>

<p>
Add <tt>constexpr</tt> to declaration of following functions and constructors:
</p>

<h3>20.2.3 [pairs] / 20.2.3p4 [pairs]</h3>

<blockquote><pre>
<ins>constexpr</ins> pair();
pair(const pair&amp;)<ins> = default</ins>;
</pre></blockquote>


<h3>20.4.1 [ratio.ratio]</h3>

<blockquote><pre>
namespace std {
  template &lt;intmax_t N, intmax_t D = 1>
  class ratio {
  public:
    static const<ins>expr</ins> intmax_t num;
    static const<ins>expr</ins> intmax_t den;
  };
}
</pre></blockquote>


<h3>20.5.2 [tuple.tuple] / 20.5.2.1p4 [tuple.cnstr]</h3>

<blockquote><pre>
<ins>constexpr</ins> tuple();
tuple(const tuple&amp;)<ins> = default</ins>;
</pre></blockquote>


<h3>20.6.3 [meta.help]</h3>

<blockquote><pre>
template &lt;class T, T v>
struct integral_constant {
  static const<ins>expr</ins> T value = v;
  typedef T value_type;
  typedef integral_constant&lt;T,v> type;
  <ins>constexpr operator value_type() { return value; }</ins>
};
</pre></blockquote>


<h3>20.7.11.1.1 [unique.ptr.dltr.dflt] / 20.7.11.1.2 [unique.ptr.dltr.dflt1]</h3>

<blockquote><pre>
<ins>consexpr default_delete();</ins>
</pre></blockquote>


<h3>20.7.11.2 [unique.ptr.single] / 20.7.11.3 [unique.ptr.runtime]</h3>

<blockquote><pre>
<ins>constexpr</ins> unique_ptr();
</pre></blockquote>

<h3>20.7.11.2.1 [unique.ptr.single.ctor]</h3>
<blockquote>
<ins>constexpr</ins> unique_ptr();

<p>
1 <i>Requires:</i> D shall be default constructible, and that construction shall not 
throw an exception. D shall not be a reference type or pointer type (diagnostic
required).
</p>
<p>
2 <i>Effects:</i> Constructs a unique_ptr which owns nothing.
</p>
<p>
3 <i>Postconditions:</i> get() == 0. get_deleter() returns a reference to a 
<del>default constructed</del><ins>value initialized</ins> deleter D.
</p>
<p>
4 <i>Throws:</i> nothing.
</p>
</blockquote>

<h3>20.8.10.2 [util.smartptr.shared] / 20.8.10.2.1 [util.smartptr.shared.const]</h3>

<blockquote><pre>
<ins>consexpr</ins> shared_ptr();
</pre></blockquote>

<h3>20.8.10.3 [util.smartptr.weak] / 20.8.10.3.1 [util.smartptr.weak.const]</h3>

<blockquote><pre>
<ins>consexpr</ins> weak_ptr();
</pre></blockquote>

<h3>20.8.10.5 [util.smartptr.enab] (2 places)</h3>

<blockquote><pre>
<ins>consexpr</ins> enable_shared_from_this();
</pre></blockquote>


<h3>20.9.3 [time.duration]</h3>

<blockquote><pre>
template &lt;class Rep, class Period = ratio&lt;1>>
class duration {
  ....
public:
  <i>// 20.9.3.1, construct/copy/destroy:</i>
  <ins>constexpr</ins> duration() = default;

  template &lt;class Rep2>
    <ins>constexpr</ins> explicit duration(const Rep2&amp; r);
  template &lt;class Rep2, class Period2>
    <ins>constexpr</ins> duration(const duration&lt;Rep2, Period2>&amp; d);

  duration(const duration&amp;) = default;

  <i>// 20.9.3.2, observer:</i>
  <ins>constexpr</ins> rep count() const;

  <i>// 20.9.3.3, arithmetic:</i>
  <ins>constexpr</ins> duration operator+() const;
  <ins>constexpr</ins> duration operator-() const;
  ...

};
</pre></blockquote>


<h3>24.6.1p3 [istream.iterator]</h3>
<blockquote><pre>
<ins>constexpr</ins> istream_iterator();
istream_iterator(istream_type&amp; s);
istream_iterator(const istream_iterator<del>&lt;T,charT,traits,Distance&gt;</del>&amp; x)<ins> = default</ins>;
~istream_iterator()<ins> = default</ins>;
</pre></blockquote>


<h3>24.6.1.1p1 [istream.iterator.cons]</h3>
<blockquote><pre>
<ins>constexpr</ins> istream_iterator();
</pre>
<blockquote>
-1- <i>Effects:</i> Constructs the end-of-stream iterator. <ins>If <tt>T</tt> is a literal type,
then this constructor shall be a constexpr constructor.</ins>
</blockquote>
</blockquote>


<h3>24.6.1.1p3 [istream.iterator.cons]</h3>
<blockquote><pre>
istream_iterator(const istream_iterator<del>&lt;T,charT,traits,Distance&gt;</del>& x)<ins> = default</ins>;
</pre>
<blockquote>
-3- <i>Effects:</i> Constructs a copy of <tt>x</tt>. <ins>If <tt>T</tt> is a literal type, then
this constructor shall be a trivial copy constructor.</ins>
</blockquote>
</blockquote>


<h3>24.6.1.1p4 [istream.iterator.cons]</h3>

<blockquote><pre>
~istream_iterator()<ins> = default</ins>;
</pre>
<blockquote>
-4- <i>Effects:</i> The iterator is destroyed. <ins>If <tt>T</tt> is a literal type, then
this destructor shall be a trivial
destructor.</ins>
</blockquote>
</blockquote>


<h3>24.6.3 [istreambuf.iterator]</h3>

<blockquote><pre>
<ins>constexpr</ins> istreambuf_iterator() throw();
<ins>istreambuf_iterator(const istreambuf_iterator&amp;)  throw() = default;</ins>
<ins>~istreambuf_iterator()  throw() = default;</ins>
</pre></blockquote>


<h3>24.6.3p1 [istreambuf.iterator]</h3>
<blockquote>
[..] The default constructor <tt>istreambuf_iterator()</tt> and the constructor
<tt>istreambuf_iterator(0)</tt> both
construct an end of stream iterator object suitable for use as an
end-of-range. <ins>All
specializations of <tt>istreambuf_iterator</tt> shall have a trivial copy
constructor, a constexpr default
constructor and a trivial destructor.</ins>
</blockquote>


<h3>30.4.1.1 [thread.mutex.class]</h3>

<blockquote><pre>
class mutex {
public:
  <ins>constexpr</ins> mutex();
  ...
</pre></blockquote>

  </body>
</html>
