This is an unofficial snapshot of the ISO/IEC JTC1 SC22 WG21 Core Issues List revision 110b. See http://www.open-std.org/jtc1/sc22/wg21/ for the official list.

2023-01-15


152. explicit copy constructors

Section: 11.4.8.2  [class.conv.ctor]     Status: TC1     Submitter: Steve Adamczyk     Date: 4 August 1999

Can a copy-constructor declared as explicit be used to copy class values implicitly? For example,

   struct X {
      X();
      explicit X(const X&);
   };
   void f(X);
   int main() { X x; f(x); }
According to 11.4.8.2 [class.conv.ctor] paragraphs 2-3,
An explicit constructor constructs objects just like non-explicit constructors, but does so only where the direct-initialization syntax (9.4 [dcl.init] ) or where casts (7.6.1.9 [expr.static.cast] , 7.6.3 [expr.cast] ) are explicitly used... A copy-constructor (11.4.5.3 [class.copy.ctor] ) is a converting constructor. An implicitly-declared copy constructor is not an explicit constructor; it may be called for implicit type conversions.
This passage would appear to indicate that the call in the example is ill-formed, since it uses neither the direct-initialization syntax nor an explicit cast. The last sentences are especially interesting in this regard, indicating that explicit and non-explicit copy constructors are handled differently.

On the other hand, 9.4 [dcl.init] paragraph 14, bullet 4, sub-bullet 2 says,

If the initialization is direct-initialization, or if it is copy-initialization where the cv-unqualified version of the source type is the same class as, or a derived class of, the class of the destination... [the] applicable constructors are enumerated (12.2.2.4 [over.match.ctor] )...
The cited passage says that
The candidate functions are all the constructors of the class of the object being initialized.

Notes from 04/01 meeting:

After the issue was accepted as a DR with the proposed resolution to change 12.2.2.4 [over.match.ctor] paragraph 1 as described below, it was noticed that 11.4.8.2 [class.conv.ctor] paragraph 3 states that:

A copy-constructor (11.4.5.3 [class.copy.ctor]) is a converting constructor.

In addition to making the proposed resolution for this issue ineffectual, the wording of paragraph 3 also contradicts that of paragraph 1:

A constructor declared without the function-specifier explicit that can be called with a single parameter specifies a conversion from the type of its first parameter to the type of its class. Such a constructor is called a converting constructor.

These considerations led to the addition of the second point of the proposed resolution.

Proposed resolution (04/01):

  1. Change the first two sentences of 12.2.2.4 [over.match.ctor] paragraph 1 to

    When objects of class type are direct-initialized (9.4 [dcl.init]), or copy-initialized from an expression of the same or a derived class type (9.4 [dcl.init]), overload resolution selects the constructor. For direct-initialization, the candidate functions are all the constructors of the class of the object being initialized. For copy-initialization, the candidate functions are all the converting constructors (11.4.8.2 [class.conv.ctor] ) of that class.
  2. Change the first sentence of 11.4.8.2 [class.conv.ctor] paragraph 3 to read:

    A non-explicit copy constructor (11.4.5.3 [class.copy.ctor]) is a converting constructor.