<!DOCTYPE html>
<html>
<head>
<title>Abolish the term "converting constructor"</title>
<style>
ins {
    color: green;
    text-decoration: underline;
}
del {
    color: red;
    text-decoration: line-through;
}
ul {
    list-style: none;
    padding: 0 0 0 1.5em;
}
li {
    padding: 0.5ex 0;
}
li::before {
    content: "\2014";
    float: left;
    margin-left: -1.5em;
}
code.example::before {
    color: #888;
    display: block;
    font-style: italic;
    counter-increment: example;
    content: "// Example " counter(example);
}
code.example {
    margin-left: 1em;
    white-space: pre;
    display: block;
}
dt {
    font-weight: bold;
}
</style>
</head>
<body style="counter-reset: example">
<h1>Abolish the term "converting constructor"</h1>
<table style="float: right">
<tr><td>Document number:</td><td>P3542R0</td></tr>
<tr><td>Date:</td><td>December 15, 2024</td></tr>
<tr><td>Audience:</td><td>EWG, CWG</td></tr>
<tr><td>Reply to:</td><td>Brian Bi (bbi5291@gmail.com)</td></tr>
</table>
<div style="clear: both"></div>
<!--
<h2>Revision history</h2>
<dl>
<dt>R1</dt>
<dd>
<ul>
<li>Blah blah</li>
</ul>
</dd>
-->
<h2>Situation</h2>
<p>The Standard defines the term <i>converting constructor</i> as <q>A
constructor that is not explicit</q> ([class.conv.ctor]/1). This term is then
used in four places in the Standard: once to redundantly point out that a
non-explicit copy or move constructor counts as a converting constructor, twice
to specify that non-explicit constructors are candidates for certain
initializations, and once in a note.</p>

<p>The first use should give the reader pause. Why does the Standard point out
that a non-explicit copy/move constructor is a converting constructor; shouldn't
this fact be an entirely obvious consequence of the fact that <q>converting
constructor</q> means any non-explicit constructor? Unfortunately, the choice of
terminology seems to be at odds with the definition: a copy or move constructor
initializes an object from another object of the same type (modulo
cv-qualification) so it does not perform what would normally be thought of as a
type conversion. It is therefore necessary to remind the reader that, in fact,
copy and move constructors still qualify as <em>converting constructors</em>
(assuming they are not explicit).</p>

<p>Equally counterintuitive is the fact that default constructors can be
converting constructors (again, as long as they are not explicit), and so can
constructors that require more than one parameter. Such constructors can be used
to form an <em>implicit conversion sequence</em> from an empty
<i>braced-init-list</i>, or a list with two or more elements, respectively, to
the constructor's class. However, C++ does not have actual <em>implicit
conversions</em> where the source is a <i>braced-init-list</i>, so such
constructors do not participate in implicit conversions even though they are
called converting constructors. (Instead of implicitly converting the list to
the destination class type, we <em>list-initialize</em> the object;
[dcl.init.general]/16.1.)</p>

<p>A further problem is that the C++ language provides mechanisms to perform
both implicit and explicit conversions; for example, [expr.static.cast]/5
describes circumstances under which <q>an expression <i>E</i> can be explicitly
converted to a type <code>T</code></q> by the <code>static_cast</code> operator 
(and specifies the semantics of such conversions). Explicit constructors are
excluded from being considered converting constructors, even though they can
still participate in explicit conversions. The notations <code>T{}</code> and
<code>T{x, y}</code> can be used to invoke constructors that accept zero and
two arguments, respectively, for an explicit conversion ([expr.type.conv]/2).
In this context, converting constructors described in the previous paragraph can
participate, but so can explicit constructors.</p>

<p>So, the use of the term <em>converting constructor</em> is problematic even
within the Standard itself. The more significant problem, however, is that
outside the Committee, people are using the term with a meaning different from
the one in the Standard. Frequently, C++ programmers think that a converting
constructor must accept a single argument or that it must have a parameter type
that sufficiently differs from that of the constructor's class (<i>i.e.</i>,
copy and move constructors don't count). I looked through 100 uses of the term
<em>converting constructor</em> on Stack Overflow questions and answers,
counting multiple uses within the same question/answer as a single use, and
categorized them according to their apparent meaning. In 4 cases the author
appeared to be unaware of the fact that explicit constructors do not qualify as
converting constructors. The remaining 96 cases broke down as follows:</p>
<ul>
<li>Converting constructor can accept any number of argument: 13</li>
<li>Converting constructor must accept one argument: 21</li>
<li>Inconclusive: 62</li>
</ul>
<ul>
<li>Converting constructor includes copy/move constructor: 14</li>
<li>Converting constructor excludes copy/move constructor: 29</li>
<li>Inconclusive: 53</li>
</ul>
<p>Indications as to what meaning was intended included, but were not limited
to: citing of explicit definitions (such as the one in the Standard or the one
on cppreference); explicitly stating that a copy/move constructor or a
multi-argument constructor is a converting constructor; explicitly stating that
a converting constructor must have a parameter whose type is different from that
of the constructor's class; using <q>copy constructor</q> and <q>converting
constructor</q> as disjoint categories; stating that a class has no converting
constructor (when in fact it does have a non-explicit copy constructor and in
some cases a non-explicit default constructor); stating that a class has one
converting constructor (thus excluding the copy constructor); or referring to
<q>the</q> converting constructor of a class in a context in which such a
designation would be ambiguous unless it was implicitly understood to exclude
the copy constructor (for example, referring to the constructor of
<code>std::variant</code> with a single forwarding reference parameter as
<q>the</q> converting constructor). Inconclusive cases included ones where a
one-parameter constructor other than a copy/move constructor was referred to as
a converting constructor; a suggestion was made to the question author to add a
converting constructor; converting constructors were compared and contrasted
with conversion functions generally; or phrasing like <q>the converting
constructor that takes <code>U</code></q> was used.</p>

<h2>Is this situation a problem?</h2>
<p>One possible response is that it doesn't really matter what term the Standard
uses, as long as the meaning of the Standard is clear. I disagree with this,
because I think that the terms chosen by the Standard clearly have influence on
how the C++ community talks about C++ constructs. For example, sometimes C++
programmers use the term <q>member</q> (of a class) to refer to any entity that
belongs to the class's scope, while sometimes they mean only data members.
Having two different definitions for <q>member</q> is unfortunate, but the
Standard has chosen the former, which in some sense makes the latter
<q>wrong</q>; the Standard is viewed as the authoritative source of definitions
for terms that refer to C++ constructs, so anyone who is using a contradictory
definition is expected to align their usage with that of the Standard.
Similarly, the Standard's consistent usage of <q>parameter</q> and
<q>argument</q> helps to move the entire C++ community in the direction of
using these terms to properly distinguish between the entities declared by the
function and the expressions used at the call site.</p>

<p>One might then suggest attempting to educate the C++ community into using the
term <q>converting constructor</q> with the meaning given to it by the
Standard. I think this is unlikely to succeed because the Standard's claim on
the definition is weak: unlike <q>member</q>, <q>parameter</q>, and
<q>argument</q>, which are each used hundreds of times in the Standard by text
prescribing their behavior and their relationship to other C++ constructs,
<q>converting constructor</q> is used only a few times, so that one rarely needs
to apply any of the rules that refer to the term. Such rules <q>anchor</q> the
term to the Standard's meaning: in order to understand what the rule means, you
need to understand the meanings of the terms that the rule applies to.
<q>Converting constructor</q> is tenuously anchored: every time someone writes
those two words, they're vastly more likely to simply be using the term to refer
to a category of constructors than to be discussing the properties given to such
constructors by the Standard. As a result, they are prone to guessing what it
means (and <q>a non-explicit constructor with one parameter, other than a
copy/move constructor</q> is the intuitively obvious meaning</q>) without coming
to a realization that this guess is wrong. The same then happens when others
read what has been written. They are unlikely to encounter someone who knows the
Standard's definition.</p>

<p>Thus, it appears that as long as the Standard continues to use the current
definition of <q>converting constructor</q> we will have a situation where two
competing definitions exist, and the one in the Standard appears to be the less
useful, less obvious one. We do the community a disservice by perpetuating this
situation: the Standard tells them that the way they're using the term is wrong,
and neither the C++ community, nor even members of this Committee, benefit much
from the Standard's definition. Those people who know both definitions are
confused: when they read the words <q>converting constructor</q> they must
figure out whether the author meant it as the Standard does, or as most other
C++ programmers do; similarly, if they want to write the words <q>converting
constructor</q> with the meaning that is more useful, they must grapple with the
fact that anyone who knows the Standard's definition will be confused. Having
two different definitions of the term makes the term harder to use.</q>

<h2>So what should we do about it?</h2>
<p>Remove the definition of <q>converting constructor</q> from the Standard and
replace all uses of it by <q>non-explicit constructor</q>.</p>

<p>It might be argued that deleting the term from the Standard makes all
existing references to it (from outside the Standard) dangling. I think this is
not really the case, just like how old answers that talk about POD classes are
still comprehensible despite the fact that the Standard no longer defines
<q>POD class</q>. In any case, I think that to the extent that the references
become dangling, there are upsides as well: the people who are currently most
likely to know the Standard's definition are also the ones who are most likely
to be aware that the Standard no longer defines the term, which will spur them
to start writing <q>non-explicit constructor</q> instead. I find this resulting
future to be more desirable than one in which the <q>official</q> definition
remains in the minority forever.</q>

<h2>Wording</h2>
<p>Wording is relative to <a href="https://wg21.link/N4993">N4993</a>.</p>

<p>Edit [class.conv.ctor]/1:</p>
<blockquote>A constructor that is not explicit (9.2.3) specifies a conversion
from the types of its parameters (if any) to the type of its class. <del>Such a
constructor is called a <i>converting constructor</i>.</del></blockquote>

<p>Strike [class.conv.ctor]/3:</p>
<blockquote><del>A non-explicit copy/move constructor ([class.copy.ctor]) is a
converting constructor.</del><br/>
<del>[<em>Note 2</em>: An implicitly-declared copy/move constructor is not an
explicit constructor; it can be called for implicit type conversions. &mdash;
<em>end note</em>]</del></blockquote>

<p>Edit [over.match.ctor]/1:</p>
<blockquote>[...] Otherwise, the candidate functions are all the
<del>converting</del><ins>non-explicit</ins> constructors (11.4.8.2) of that
class. [...]</blockquote>

<p>Edit [over.match.copy]/1:</p>
<blockquote>[...] Assuming that <q><i>cv1</i> <code>T</code></q> is the type of 
the object being initialized, with <code>T</code> a class type, the candidate
functions are selected as follows:
<ul><li>The <del>converting</del><ins>non-explicit</ins> constructors of
<code>T</code> are candidate functions.</li><li>[...]</li></ul></blockquote>

<p>Edit [over.match.list]/1:</p>
<blockquote>[...] In copy-list-initialization, if an explicit constructor is
chosen, the initialization is ill-formed.<br/>
[<em>Note 1</em>:  This differs from other situations (12.2.2.4, 12.2.2.5),
where only <del>converting</del><ins>non-explicit</ins> constructors are
considered for copy-initialization. This restriction only applies if this
initialization is part of the final result of overload resolution. &mdash;
<em>end note</em>]
