<html>

<head>
  <meta name="description" content="Resolving LWG #2307 for C++20: Consistently Explicit Constructors">
  <meta name="keywords" content="C++,cplusplus,wg21,explicit,constructors,library,process">
  <meta name="author" content="Alisdair Meredith">

  <title>Resolving LWG #2307 for C++20: Consistently Explicit Constructors</title>

  <style type="text/css">
    ins {background-color:#A0FFA0}
    del {background-color:#FFA0A0}
    p {text-align:justify}
    li {text-align:justify}
    blockquote.note
    {
      background-color:#E0E0E0;
      padding-left: 15px;
      padding-right: 15px;
      padding-top: 1px;
      padding-bottom: 1px;
    }

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.5em padding-right: 0.5em; ; }

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

  </style>
</head>

<body>
<table>
<tr>
  <td align="left">Doc. no.</td>
  <td align="left">P1374R0</td>
</tr>
<tr>
  <td align="left">Date:</td>
  <td align="left">2018-11-22</td>
</tr>
<tr>
  <td align="left">Project:</td>
  <td align="left">Programming Language C++</td>
</tr>
<tr>
  <td align="left">Audience:</td>
  <td align="left">Library Evolution Working Group</td>
</tr>
<tr>
  <td align="left"> </td>
  <td align="left">Evolution Working Group</td>
</tr>
<tr>
  <td align="left"> </td>
  <td align="left">Library Working Group</td>
</tr>
<tr>
  <td align="left">Reply to:</td>
  <td align="left">Alisdair Meredith &lt;<a href="mailto:ameredith1@bloomberg.net">ameredith1@bloomberg.net</a>&gt;</td>
</tr>
</table>

<h1>Resolving LWG #2307 for C++20: Consistently Explicit Constructors</h1>

<h2>Table of Contents</h2>
<ol>
<li><a href="#rev.hist">Revision History</a></li>
  <ul>
  <li><a href="#rev.0">Revision 0</a></li>
  </ul>
<li><a href="#1.0">1 Introduction</a></li>
<li><a href="#2.0">2 Stating the problem</a></li>
  <ul>
  <li><a href="#2.1">2.1 What is the Current Guideline?</a></li>
  <li><a href="#2.2">2.2 How was the Current Guideline Formed?</a></li>
  <li><a href="#2.3">2.3 Why Do We Have A Problem?</a></li>
  <li><a href="#2.4">2.4 What Have We Been Doing About The Problem?</a></li>
  <li><a href="#2.5">2.5 Why Have We Not Solved The Problem?</a></li>
  <li><a href="#2.6">2.6 Further Insights</a></h3>
  </ul>
<li><a href="#3.0">3 Propose Solution</a></li>
  <ul>
  <li><a href="#3.1">3.1 The Wording is Complete and Reviewed</a></li>
  <li><a href="#3.2">3.2 Applying a New Consistently Will Be Simpler</a></li>
  <li><a href="#3.3">3.3 P1163R0 is (Essentially) Not A Breaking Change</a></li>
  <li><a href="#3.4">3.4 There is Still Time for a More Complete Resolution</a></li>
  </ul>
<li><a href="#4.0">4 Other Directions</a></li>
  <ul>
  <li><a href="#4.1">4.1 Status Quo</a></li>
  <li><a href="#4.2">4.2 Revert All C++20 Changes</a></li>
  <li><a href="#4.3">4.3 Move Issue to LEWG for C++20</a></li>
  <li><a href="#4.4">4.4 Invite LWG to Propose Direction to LEWG for C++20</a></li>
  <li><a href="#4.5">4.5 Move Issue to LEWG, With No Target</a></li>
  <li><a href="#4.6">4.6 Move Issue to LEWGI</a></li>
  <li><a href="#4.7">4.7 Send Back to EWG to Ammend Initialization Rules for Simpler Consistency</a></li>
  </ul>
<li><a href="#5.0">5 Formal Wording</a></li>
<li><a href="#6.0">6 Acknowledgements</a></li>
<li><a href="#7.0">7 References</a></li>
</ol>


<h2><a name="rev.hist">Revision History</a></h2>

<h3><a name="rev.0">Revision 0</a></h3>
<p>
Original version of the paper for the 2018 post-San Diego mailing.
</p>


<h2><a name="1.0">1 Introduction</a></h2>
<p>
Library issue
<a href="http://cplusplus.github.io/LWG/lwg-active.html#2307">LWG #2307</a>
is a request to put the library into a consistent state with respect to
multi-argument explicit constructors.  While the resolution and wording were
approved by the LWG prior to the most recent San Diego meeting, the LEWG would
like to revisit the subject, and requested the paper be pulled until a clear
policy for explicit constructors has been agreed.
</p>

<h2><a name="2.0">2 Stating the problem</a></h2>
<p>
</p>

<h3><a name="2.1">2.1 What is the Current Guideline?</a></h3>
<p>
The current guideline was never explicitly put into print, but the informal
rule-of-thumb followed by LWG (prior to the formation of LEWG) during the C++11
timeframe was:
</p>
<ul>
  <li>
  Single argument constructors that are not copy or move constructors should be
  marked as <tt>explicit</tt> unless there is a good reason not to.
  </li>
  <li>
  All other constructors should <em>not</em> be marked <tt>explicit</tt> unless
  the is a good reason to do so.
  </li>
</ul>

<p>
An example of wanting an implicit conversion came up in
<a href="http://cplusplus.github.io/LWG/lwg-defects.html#925">LWG #925</a>
where we changed the standard to allow implicit conversion of rvalues of unique
ownership smart pointers to <tt>shared_ptr</tt> (but not from lvalues).
</p>
<p>
An example of adding <tt>explicit</tt> to multiple-argument constructors can be
seen in <tt>pair</tt> and <tt>tuple</tt>, where we want to reflect the implicit
conversion rules for the wrapped type.  This models the rules of aggregate
initialization followed by the language in [dcl.init.aggr] using copy
initialization for each member supplied with an initializer.
</p>
<p>
Note that the currently guideline is not clear in the presence of variadic
constructors, which may also act as single-argument converting constructors, or
even default constructors, depending on how they are invoked.
</p>

<h3><a name="2.2">2.2 How Was The Current Guideline Formed?</a></h3>
<p>
The basis of the current guideline came with direction from EWG while trying to
resolve
<a href="https://cplusplus.github.io/LWG/lwg-closed.html#1153">LWG #1153</a>.
The question of how to review the whole library, and which combinations of
arguments to make explicit, was considered from a high level only, and the
EWG designers of the unified initialization syntax pointed out that it was
intentional to support the multiple-argument cases constructing from a
brace-initializer list, and the library should think very carefully before
disabling an intended feature (through use of <tt>explicit</tt>).  Lacking any
guiding principle to apply explicit without experience, LWG followed the EWG
encouragement and did not consider the issue further, closing the issue NAD.
</p>
<p>
We now have most of a decade's experience with the new forms of initialization,
and some additional guidance is emerging.  It may well be time to revisit that
earlier decision.
</p>

<h3><a name="2.3">2.3 Why Do We Have A Problem?</a></h3>
<p>
In the original C++98 standard, the <tt>explicit</tt> keyword had no effect
unless a constructor was called with a single argument.  As a matter of
convenience, several classes (notably containers) provided constructors with a
number of default arguments.  If these constructors could be called with a
single argument, they would also be marked <tt>explicit</tt>.
</p>
<p>
When C++11 changed the semantics so that <tt>explicit</tt> had a new meaning
for these multiple-argument cases, it was not immediately noticed.  Since then,
there has been concern that the design inherited from the core language change
was never the intended library design.  In particular, the issue of
<tt>explicit</tt> default constructors was handled for C++14 in issue
</p>
<a href="http://cplusplus.github.io/LWG/lwg-defects.html#2193">LWG #2193</a>
and in the paper
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0935r0">P0935R0</a>
from Tim Shen, adopted at the Jacksonville 2018 meeting,

<h3><a name="2.4">2.4 What Have We Been Doing About The Problem?</a></h3>
<p>
Since the revised meaning of <tt>explicit</tt> was discovered, the LWG has been
processing an ongoing sequence of defect reports.  See
<a href="#7.0">References</a> for a list.  The last part of the puzzle passed
LWG review at the Batavia 2018 extra-curricular LWG meeting, and was expected
to be adopted at the San Diego 2018 meeting.  It is believed, after our most
careful review of the current wording, that this should be the last such issue
unless a new library is adopted without consideration of the informal
convention.
</p>

<h3><a name="2.5">2.5 Why Have We Not Solved The Problem?</a></h3>
<p>
The final paper resolving the legacy wording was Tentatively Ready for polling
in San Diego, but the LEWG questioned whether the informal consistency rule
being applied was the correct choice.  LEWG requested that the final paper be
withdrawn while they consider anew what the desired rule for applying
<tt>explicit</tt> to constructors should be.  In particular, concerns were
raised that making allowing multi-argument constructors constructors to be
implicit (the default, and current state for most of the library) could easily
lead to mistakes with accidental constructions.
</p>
<p>
The minutes to not suggest anyone familiar with the history of the last time
this was discussed with EWG was present to explain the current policy, nor was
consultation with EWG considered.
</p>
<p>
Polls indicate a desire for LEWG to formulate the policy for LWG to apply, and
minimal support for applying the current paper.  There was no indication of who
would do the work to propose a new policy, nor direction polls on what it
should be, although they may have apparent and obvious to those present in the
room.  No timetable for the new policy was suggested, nor guidance given for
new papers coming through the process.
</p>

<h3><a name="2.6">2.6 Further Insights</a></h3>
<p>
During informal discussion since the polls were taken (and I was not present in
the room to know if this reflects the feel of the group, or just a few
individuals I spoke to since) there seemed to be a feeling that passing
sequences of brace-lists as arguments to functions was fragile and confusing,
much like passing a long sequence of <tt>true</tt> and <tt>false</tt> flags
can make it difficult to understand which flag is being set, often leading to
use of enumerations in such APIs.  Making such constructors <tt>explicit</tt>
would at least require tagging with the type to be constructed, which is the
only elided information today, and the root of much of the problem.  There was
much less concern about using brace lists for return values, as the return type
is clearer.  Perhaps another tweak of the initialization rules in core would
better address the concerns being raised by LEWG?  At least it seems that the
two groups should be talking about expected design and usage of the language
feature, before setting a new library-wide policy.
</p>
<p>
The meeting minutes show concerns that there is code breakage with both adding
and removing <tt>explicit</tt> from constructors in this context, so any change
would be equally concerning.  This discounts existing experience with the
Library already making such changes in the past (see
<a href="#7.0">References</a> below).  In general, removing <tt>explicit</tt>
(other than the single-argument case) allows code that would not compile before
to compile, but does not break or change existing code without hitting corners
of SFINAE detection that we historically discount, for fear of never being able
to change the library in even the most benign ways.  There would be a
compatibility concern adding <tt>explicit</tt> where it is absent today (not
proposed by
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p1163r0">P1163R0</a>),
and this may become an issue if LEWG do not expect to have their new guidelines
in place for C++20.
</p>


<h2><a name="3.0">3 Propose Solution</a></h2>
<p>
The proposed solution is to adopt
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p1163r0">P1163R0</a> 
for C++20, and close LWG issue #2307 as resolved.  Meanwhile, EWG and LEWG can
agree a preferred policy for a future standard (potentially C++20).  Once such
a policy is agreed, it will be much simpler to review the library and apply it,
as the document will be moving from one consistent state to another, and the
pattern of edits should be regular.
</p>

<p>
There are several reasons why we should immediately adopt 
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p1163r0">P1163R0</a>,
even if another approach from the evolutionary groups is pending.
</p>

<h3><a name="3.1">3.1 The Wording is Complete and Reviewed</a></h3>
<p>
First, the wording is complete, and approved by the Library Working Group.  We
are not saving any of the limited LWG resources by asking them to complete this
task, as they have already completed the work.  The final paper was pulled from
the planned motions page at the request of LEWG in San Diego.
</p>

<h3><a name="3.2">3.2 Applying a New Consistently Will Be Simpler</a></h3>
<p>
Putting the working paper into a consistent state will make it easier to apply
an update for a preferred consistency in the future.  The author of the new
paper can search and apply a (presumably) simple mechanical transformation
rather than having to look out for, and account for, accidentally explicit
constructors that are a consequence of the history of the specification, and
not a deliberately designed intent where you might go looking for them.
</p>

<h3><a name="3.3">3.3 P1163R0 is (Essentially) Not A Breaking Change</a></h3>
<p>
Any change to C++ libraries can be observed though SFINAE tricks (and the use
of Concepts in the future) so every change is potentially breaking in that
sense.  Putting aside such concerns, the changes proposed in
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p1163r0">P1163R0</a>
are entirely enabling, turning previously non-compiling code into code with a
well-defined meaning.
</p>

<h3><a name="3.4">3.4 There is Still Time for a More Complete Resolution</a></h3>
<p>
We anticipate at least four more meetings, including ballot comment resolution,
before C++20 is published.  If there is a strong desire to replace the current
rule of thumb with a more precise convention to follow, we will not be harmed
by landing the completed thought, even if it would allow programs to compile
that might not under a new convention.  If we are to change convention to adopt
a more widespread use of <tt>explicit</tt> then it <i>is</i> going to be a
breaking change, and there is time to agree and adopt that new convention prior
to publishing any new standard.  By the same argument, we could defer adopting
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p1163r0">P1163R0</a>
until the final ballot resolution meeting.  Such a delay mostly gives up on the
convenience of applying that new convention over an inconsistent document,
leading to more LWG work to get that final resolution right.
</p>

<h2><a name="4.0">4 Other Directions</a></h2>
<p>
Several other directions were considered by the author, in the event that the
proposed solution is not acceptable to the committee.
</p>

<h3><a name="4.1">4.1 Status Quo</a></h3>
<p>
Status quo is that LWG has a priority 2 Open issue that it cannot make progress
on without direction from LEWG.  C++20 is published with this issue Open, and
we get more comfortable releasing standards with high priority issues.  This is
my least preferred option.
</p>
<p>
Optionally, lower the issue priority to 3 or 4, as we would not expect to make
progress until after C++20, or at least not until ballot resolution.
</p>

<h3><a name="4.2">4.2 Revert All C++20 Changes</a></h3>
<p>
This is a more aggressive notion of status quo, resetting all use of
<tt>explicit</tt> in constructors back to the C++17 state, pending eventual
guidance on how to apply a consistent transformation to all library clauses of
the standard.  At a minimum, this would mean reverting paper
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0935r0">P0935R0</a>,
but also reviewing the issues list for issues in WP status that may have been
impacted by this discussion.
</p>
<p>
This option may would compatible with also adopting one of the following
choices.
</p>

<h3><a name="4.3">4.3 Move Issue to LEWG for C++20</a></h3>
<p>
LWG moves the issue to LEWG status, expecting guidance on the new principle in
time to apply it to C++20.  This will mean working on the issue in preference
to some other work, and finding LWG time to review and apply a new direction
consistently across the library.  This may be desirable, but seems a poor use
of resources at this stage of the process, with so many other papers vying for
attention.
</p>

<h3><a name="4.4">4.4 Invite LWG to Propose Direction to LEWG for C++20</a></h3>
<p>
This is similar to option 4.2, only LWG are responsible for proposing a new
direction that they can consistently apply in this time-frame, and LEWG get
veto privilege over any such direction.  This reflects where we are today,
leaving the priority issue in LWG, but taking more time to find, propose, and
word a new solution.
</p>

<h3><a name="4.5">4.5 Move Issue to LEWG, With No Target</a></h3>
<p>
Move the issue to LEWG status, without direction for a time-frame.  LEWG will
prioritize this issue according to their interest level relative to the rest of
their workload, and the standard remains in an inconsistent (but repeatedly
shipped) state.
</p>

<h3><a name="4.6">4.6 Move Issue to LEWGI</a></h3>
<p>
As we have no clear direction at the moment, we could move the work all the way
out to LEWGI.  Close the issue as NAD in on the Library Issues List, and invite
interested parties to prepare presentations for LEWGI to incubate, until there
is consensus on a new direction worth LEWG time to review.
</p>

<h3><a name="4.7">4.7 Send Back to EWG to Ammend Initialization Rules for Simpler Consistency</a></h3>
<p>
Set the issue to the rarely used EWG status, and send back over to the language
evolution group to tweak the initialization rules further, so that an intuitive
direction for LEWG to apply to the standard library emerges.
</p>


<h2><a name="5.0">5 Formal Wording</a></h2>
<p>
Apply the wording changes contained in
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p1163r0">P1163R0</a> 
</p>


<h2><a name="6.0">6 Acknowledgements</h2>
<p>
Thanks to Nevin Lieber for performing the initial library review and providing
wording in
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p1163r0">P1163R0</a>.
</p>


<h2><a name="7.0">7 References</h2>
<ul>
  <li><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p1163r0">P1163R0</a>
    Explicitly Implicifying explicit Constructors,
    Nevin Lieber
  </li>
  <li>
    <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0935r0">P0935R0</a>
    Eradicating unnecessarily explicit default constructors from the standard library,
    Tim Song
  </li>
  <li>
    <a href="http://cplusplus.github.io/LWG/lwg-active.html#2307">LWG #2307</a>
    Should the Standard Library use <tt>explicit</tt> only when necessary?
  </li>
  <li>
    <a href="http://cplusplus.github.io/LWG/lwg-defects.html#2193">LWG #2193</a>
    Default constructors for standard library containers are explicit
  </li>
  <li>
    <a href="http://cplusplus.github.io/LWG/lwg-defects.html#2051">LWG #2051</a>
    Explicit <tt>tuple</tt> constructors for more than one parameter
  </li>
  <li>
    <a href="http://cplusplus.github.io/LWG/lwg-defects.html#1430">LWG #1430</a>
    <tt>unordered_multiset</tt> constructor accepting an allocator as a single parameter should be explicit
  </li>
  <li>
    <a href="http://cplusplus.github.io/LWG/lwg-defects.html#1429">LWG #1429</a>
    <tt>unordered_set</tt> constructor accepting an allocator as a single parameter should be explicit
  </li>
  <li>
    <a href="http://cplusplus.github.io/LWG/lwg-defects.html#1428">LWG #1428</a>
    <tt>unordered_multimap</tt> constructor accepting an allocator as a single parameter should be explicit
  </li>
  <li>
    <a href="http://cplusplus.github.io/LWG/lwg-defects.html#1427">LWG #1427</a>
    <tt>unordered_map</tt> constructor accepting an allocator as a single parameter should be explicit
  </li>
  <li>
    <a href="http://cplusplus.github.io/LWG/lwg-defects.html#1426">LWG #1426</a>
    <tt>multiset</tt> constructor accepting an allocator as a single parameter should be explicit
  </li>
  <li>
    <a href="http://cplusplus.github.io/LWG/lwg-defects.html#1425">LWG #1425</a>
    <tt>set</tt> constructor accepting an allocator as a single parameter should be explicit
  </li>
  <li>
    <a href="http://cplusplus.github.io/LWG/lwg-defects.html#1424">LWG #1424</a>
    <tt>multimap</tt> constructor accepting an allocator as a single parameter should be explicit
  </li>
  <li>
    <a href="http://cplusplus.github.io/LWG/lwg-defects.html#1423">LWG #1423</a>
    <tt>map</tt> constructor accepting an allocator as a single parameter should be explicit
  </li>
  <li>
    <a href="http://cplusplus.github.io/LWG/lwg-defects.html#1400">LWG #1400</a>
    FCD <tt>function</tt> does not need an explicit default constructor
  </li>
  <li>
    <a href="http://cplusplus.github.io/LWG/lwg-defects.html#1399">LWG #1399</a>
    <tt>std::function</tt> does not need an explicit default constructor
  </li>
  <li>
    <a href="http://cplusplus.github.io/LWG/lwg-defects.html#925">LWG #925</a>
    <tt>shared_ptr</tt>'s explicit conversion from <tt>unique_ptr</tt>
  </li>
  <li>
    <a href="http://cplusplus.github.io/LWG/lwg-defects.html#789">LWG #789</a>
    <tt>xor_combine_engine(result_type)</tt> should be explicit
  </li>
  <li>
    <a href="https://cplusplus.github.io/LWG/lwg-closed.html#1153">LWG #1153</a>
    Standard library needs review for constructors to be explicit to avoid treatment as initializer-list constructor
  </li>
</ul>

</body>
</html>
