Where exactly in the C ++ 14 standard does this allow you to use a custom conversion function in direct initialization?

For example, in the fragment below the user-defined conversion function C::operator A() implicitly called to convert an lvalue of type C to prvalue of type A , which copies-initializes the variable A to direct initialization .

 struct A {}; struct C { operator A() { return A(); }; }; int main() { C c; A a(c); } 

I just want to know where this is described in the C ++ 14 standard. I have a feeling that the answer is in [over.match.copy] / 1 market (1.2), but I had a problem with the heading of the Copy-Initialize section custom conversion .

+5
source share
1 answer

There are two constructors in A that can be called with a single argument:

 A(A const&); // copy constructor A(A&& ); // move constructor 

In any case, [dcl.init.ref] explains how we can initialize the link:

A reference of type "cv1 T1 " is initialized by an expression of type "cv2 T2 " as follows:
- If the link is an lvalue reference and an initializer expression
- is an lvalue value (but not a bit field), and "cv1 T1 " is reference compatible with "cv2 T2 ", or
& has a class type (i.e. t29> ", where" cv1 T1 "is reference compatible with" cv3 T3 "(this conversion is selected by listing the applicable conversion functions ([over.match.ref]) and choosing the best one due to resolution overload)
then the link is bound to the lvalue initializer expression in the first case and to the result of the lvalue conversion in the second case (or, in any case, to the corresponding subobject of the object’s base class).

We have references of type A or A const , which are initialized by an expression of type C , which is a class type that is not associated with reference A To check if it can be converted to the cv3 T3 reference type, we check [over.match.ref] :

The transformation functions of S and its base classes are considered. Those implicit conversion functions that are not hidden inside S and do not give the type "lvalue reference to cv2 T2 " (when initializing a link to an lvalue or rvalue function reference) or "cv2 T2 " or "rvalue reference to cv2 T2 " (when initializing a link rvalue or function references lvalue) , where "cv1 T " refers to "cv2 T2 ", are candidate functions. For direct initialization [...]

Therefore, for the copy constructor, we consider those conversion functions that give A& , and for the move constructor, we consider those conversion functions that give A or A&& . We do not have the first, but we have the last: operator A() .

This makes move constructor A viable constructor, but not copy constructor A Since we have only one viable candidate, this is the trivially best viable candidate.

0
source

Source: https://habr.com/ru/post/1257547/


All Articles