Second standard custom transform conversion sequence

I have a misunderstanding about the terms of the standard conversion sequence. I came across the following quote N3797 ยง8.5.3 / 5 [dcl.init.ref]:

- If the initializer expression

is the x-value (but not the bitfield), the prvalue class, array value or lvalue function and "cv1 T1" refer to "cv2" T2 "or

     

- has a class type (ie T2 is a class type), where T1 is not a reference associated with T2, and can be converted to an xvalue class, prvalue class, or function lvalue of type "cv3 T3", where "cv1 T1" is reference-compatible with "cv3 T3" (see 13.3.1.6),

[..] In the second case, if the reference is an rvalue reference and the second standard conversion sequence of the custom conversion sequence includes an lvalue-to-rvalue conversion, the program is ill-formed.

What is Standard Conversion Funnel 2? I thought there was a standard conversion sequence that included all the necessary standard conversions (user-defined and implicit).

+3


source to share


2 answers


[over.ics.user]:

A custom conversion consists of an initial conversion standard sequence followed by a custom conversion (12.3) and then a second conversion standard sequence . [...]
The second standard conversion sequence converts the result of the custom conversion to the target type for the sequence.

eg. for

struct A
{
    operator int();
};

void foo(short);

foo(A());

      



The second standard conversion sequence converts the int

prvalue to a parameter foo

, that is short

. The first standard conversion sequence converts an object A

to A

(implicit object parameter operator int

), which is an identity conversion.
For reference, the rule you quoted provides an example:

struct X {
    operator B();
    operator int&();
} x;

int&& rri2 = X(); // error: lvalue-to-rvalue conversion applied to
                  // the result of operator int&

      

operator int&

Select here with overload resolution. The return value is an lvalue reference to int

. This requires an lvalue-to-rvalue conversion to initialize the reference, and that's exactly what the quote prevents: Lvalues โ€‹โ€‹should not bind to rvalue references.

+2


source


What the standard conversion term means is discussed in the following section of the C ++ standard:

4 Standard conversions [conv]

  • Standard conversions are implicit conversions with a built-in value. Clause 4 lists the complete set of such transformations. A standard conversion sequence is a sequence of standard conversions in the following order:

    - Zero or one conversion from the following set: lvalue-to-rval conversion, array-to-pointer conversion, and function-to-pointer conversion.

    - Zero or one conversion from the following set: integral promotions, floating point promotions, integral conversions, floating point conversions, floating integral conversions, pointer conversions, pointers to member conversions, and boolean conversions.

    - Zero or one qualification conversion.

    [Note: the standard conversion sequence can be empty, i.e. it cannot consist of transformations. - end of note]

A standard conversion sequence will be applied to the expression, if necessary, to convert it to the desired target type.

In other words, a standard conversion is a set of built-in rules that the compiler can apply when converting from one type to another. These built-in conversions include:

  • No conversions
  • Lvalue-to-rvalue conversion
  • Converting an array to a pointer
  • Converting functions to a pointer
  • Qualification transformations
  • Integral promotions
  • Floating point advance
  • Integral transformations
  • Floating point conversions
  • Floating integral transforms
  • Pointer Conversions
  • Converting pointers to members
  • Logical transformations

A standard conversion funnel can be displayed twice during a custom conversion funnel - before and / or after a custom conversion:

ยง 13.3.3.1.2 Custom conversion sequences [over.ics.user]

  • A custom conversion sequence consists of an initial conversion standard sequence, followed by a custom conversion (12.3), followed by a second conversion standard sequence. If a user-defined conversion is specified by a constructor (12.3.1), the initial conversion standard sequence converts the source type to the type required by the constructor argument. If a custom conversion is specified by a conversion function (12.3.2), the initial conversion standard converts the source type to a parameter of the implicit conversion function object.

  • The second standard conversion sequence converts the result of the custom conversion to the target type for the sequence. Because the implicit conversion sequence is an initialization, special custom conversion initialization rules are applied when choosing the best custom conversion for the custom conversion sequence (see 13.3.3 and 13.3.3.1).

Having said that, for the next transformation:

A a;
B b = a;

      

  • the compiler will look for a conversion to constructor B

    that can take an instance A

    (source type) through some initial standard conversion sequence to then perform that custom conversion through the selected constructors, and then apply another standard conversion - a second standard conversion - to convert the resulting custom conversion type to target type;

    or

  • the compiler will look for a conversion to function A

    that can be called after some initial standard implicit context conversion sequence, which can then convert the instance A

    to some type that is converted via another standard conversion โ€” a second standard conversion โ€” to the target type B

    .



As a tangible example, consider the following transformation:

struct A
{
    operator int() const;
};

A a;
bool b = a;

      

The compiler considers the following custom conversion sequence:

  • Initial standard conversion: converting qualification A*

    in const A*

    to call const

    -qualified operator int() const

    .

  • Custom Conversion: Converting A

    to int

    via a custom conversion function.

  • Second standard conversion: boolean conversion int

    to bool

    .

The case you are asking about can be divided as follows:

struct A
{
    operator int&();
};

int&& b = A();

      

  • Source type A

    .
  • Target type int&&

    .
  • A custom conversion sequence is a conversion A

    to int&&

    .
  • The initial standard conversion sequence is not a conversion at all.
  • A custom conversion is a conversion A

    to int&

    .
  • The second standard conversion sequence (converting the result of the custom conversion to the target type), which is part of the general custom conversion sequence, will be the standard conversion int&

    to int&&

    - Lvalue-to-rvalue conversion here. This conversion is considered as int&

    and int&&

    is a reference-compatible types. According to section ยง8.5.3 [dcl.init.ref] / p5 below:

[...] if the reference is an rvalue reference, and the second standard conversion sequence of the custom conversion sequence includes an lvalue-to-rval conversion, the program is ill-formed.

this transformation is not applicable in the general custom transformation sequence.

0


source







All Articles