This is an unofficial snapshot of the ISO/IEC JTC1 SC22 WG21 Core Issues List revision 115e. See http://www.open-std.org/jtc1/sc22/wg21/ for the official list.
2024-11-11
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):
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.
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.