Copy-initialization of class by user-defined conversion [over.match.copy]/1

47 views
Skip to first unread message

Belloc

unread,
Sep 24, 2016, 9:57:11 AM9/24/16
to ISO C++ Standard - Discussion
[over.match.copy]/1 (emphasis is mine):

Under the conditions specified in 8.5, as part of a copy-initialization of an object of class type, a user-defined conversion can be invoked to convert an initializer expression to the type of the object being initialized.
Overload resolution is used to select the user-defined conversion to be invoked. [ Note: The conversion performed for indirect binding to a reference to a possibly cv-qualified class type is determined in terms of
a corresponding non-reference copy-initialization. —end note ] Assuming that “cv1 T” is the type of the object being initialized, with T a class type, the candidate functions are selected as follows:

(1.1)  — The converting constructors (12.3.1) of T are candidate functions.

(1.2)  — When the type of the initializer expression is a class type “cv S”, the non-explicit conversion functions of S and its base classes are considered. When initializing a temporary to be bound to the first parameter
              of a constructor that takes a reference to possibly cv-qualified T as its first argument, called with a single argument in the context of direct-initialization of an object of type “cv2 T”, explicit conversion
              functions are also considered. Those that are not hidden within S and yield a type whose cv-unqualified version is the same type as T or is a derived class thereof are candidate functions. Conversion functions
              that return “reference to X” return lvalues or xvalues, depending on the type of reference, of type X and are therefore considered to yield X for this process of selecting candidate functions.

While trying to understand bullet point (1.2) above, I was intrigued with the change from "cv1 T" to "cv2 T" in the type of the object being initialized. I thought this was just a minor editorial error. But then I found out this DR 1556 which seems to confirm the wording above. But I still don't understand what is behind this change from cv1 T to cv2 T. For me, the wording prior to this change in bullet point (1.2) was correct. Note that the sentence

When initializing a temporary to be bound to the first parameter of a constructor that takes a reference to possibly cv-qualified T as its first argument, called with a single argument in the context of direct-initialization, explicit conversion functions are also considered.

describes the special case where an explicit conversion function is allowed to be invoked in the context of direct-initialization to bind the temporary returned by the function to the first parameter of a (copy or move) constructor that takes a reference to a possibly cv-qualified T.

Johannes Schaub

unread,
Sep 24, 2016, 10:10:16 AM9/24/16
to std-dis...@isocpp.org
It does not desribe that. The sentence prior to the change also
applies to the initialization of the temporary string which is bound
to "x" below, but the ctor is not a copy or move constructor

class X {
public:
X(const string& x);
};

class Y { explicit operator string(); };

X x((Y()));

Here, the implicit conversion sequence is from "Y" to "string" which
copy initializes a temporary "const string" from "Y()" by calling the
explicit conversion function. But the direct initialization context
initializes an "X", not a "string". Therefore, it says "cv2 T". So
that the direct initialization context must be "cv-qualifier string".

Belloc

unread,
Sep 24, 2016, 1:46:58 PM9/24/16
to ISO C++ Standard - Discussion


On Saturday, September 24, 2016 at 11:10:16 AM UTC-3, Johannes Schaub wrote:


It does not desribe that. The sentence prior to the change also
applies to the initialization of the temporary string which is bound
to "x" below, but the ctor is not a copy or move constructor

    class X {
    public:
       X(const string& x);
    };

    class Y { explicit operator string(); };

    X x((Y()));

Here, the implicit conversion sequence is from "Y" to "string" which
copy initializes a temporary "const string" from "Y()" by calling the
explicit conversion function. But the direct initialization context
initializes an "X", not a "string". Therefore, it says "cv2 T". So
that the direct initialization context must be "cv-qualifier string".

Even if what you say were (or was*) correct, the new wording should be "an object of type cv2 T2" and not "an object of type cv2 T". But in fact, what you say doesn't seem to be correct, as your snippet doesn't compile in C++14 and C++11. 

For me, the intention here is to allow explicit conversion functions that produce a temporary object of type T (an only T) to be copied or moved, to the object being initialized. This was what Richard Smith told me a few days ago, although without quoting this paragraph. See his answer to a question of mine here

The text is also clear about this: When initializing a temporary to be bound to the first parameter of a constructor that takes a reference to possibly cv-qualified T.

(*) I really don't know which should be the correct form to use here.
Reply all
Reply to author
Forward
0 new messages