Distinguishing between user-defined conversion sequences by the initial standard conversion sequence

后端 未结 1 1278
耶瑟儿~
耶瑟儿~ 2021-01-01 06:18

The standard appears to provide two rules for distinguishing between implicit conversion sequences that involve user-defined conversion operators:

c++

相关标签:
1条回答
  • 2021-01-01 07:03

    The trick here is that converting from a class type to a non-class type doesn't actually rank any user-defined conversions as implicit conversion sequences.

    struct A {
        operator int();
        operator char() const;
    } a;
    void foo(double);
    int main() {
        foo(a);
    }
    

    In the expression foo(a), foo obviously names a non-overloaded non-member function. The call requires copy-initializing (8.5p14) the function parameter, of type double, using the single expression a, which is an lvalue of class type A.

    Since the destination type double is not a cv-qualified class type but the source type A is, the candidate functions are defined by section 13.3.1.5, with S=A and T=double. Only conversion functions in class A and any base classes of A are considered. A conversion function is in the set of candidates if:

    • It is not hidden in class A, and
    • It is not explicit (since the context is copy-initialization), and
    • A standard conversion sequence can convert the function's return type (not including any reference qualifiers) to the destination type double.

    Okay, both conversion functions qualify, so the candidate functions are

    A::operator int();        // F1
    A::operator char() const; // F2
    

    Using the rules from 13.3.1p4, each function has the implicit object parameter as the only thing in its parameter list. F1's parameter list is "(lvalue reference to A)" and F2's parameter list is "(lvalue reference to const A)".

    Next we check that the functions are viable (13.3.2). Each function has one type in its parameter list, and there is one argument. Is there an implicit conversion sequence for each argument/parameter pair? Sure:

    • ICS1(F1): Bind the implicit object parameter (type lvalue reference to A) to expression a (lvalue of type A).
    • ICS1(F2): Bind the implicit object parameter (type lvalue reference to const A) to expression a (lvalue of type A).

    Since there's no derived-to-base conversion going on, these reference bindings are considered special cases of the identity conversion (13.3.3.1.4p1). Yup, both functions are viable.

    Now we have to determine if one implicit conversion sequence is better than the other. This falls under the fifth sub-item in the big list in 13.3.3.2p3: both are reference bindings to the same type except for top-level cv-qualifiers. Since the referenced type for ICS1(F2) is more cv-qualified than the referenced type for ICS1(F1), ICS1(F1) is better than ICS1(F2).

    Therefore F1, or A::operator int(), is the most viable function. And no user-defined conversions (with the strict definition of a type of ICS composed of SCS + (converting constructor or conversion function) + SCS) were even to be compared.

    Now if foo were overloaded, user-defined conversions on the argument a would need to be compared. So then the user-defined conversion (identity + A::operator int() + int to double) would be compared to other implicit conversion sequences.

    0 讨论(0)
提交回复
热议问题