Worst conversion sequence in list-initialization - c++

I don't understand how worst conversion sequences for initializer_list are ranked during overload resolution. For example:
#include <initializer_list>
void fnc (std::initializer_list<int>){}
void fnc (std::initializer_list<long>){}
struct CL1 {
operator short(){return 1;} };
struct CL2 {
operator short(){return 1;} };
int main() {
CL1 cl1;
CL2 cl2;
fnc ({cl1, cl2});
}
Here is a call of overloaded fnc function and overload resolution finds the best-viable function. The candidates are 2 functions which are ranked by comparing their needed conversion sequences.
The Standard (n4296) 13.3.3.1.5/4 [over.ics.list] says:
Otherwise, if the parameter type is std::initializer_list and all the
elements of the initializer list can be implicitly converted to X, the
implicit conversion sequence is the worst conversion necessary to
convert an element of the list to X
For std::initializer_list<int> both conversions (CL1 -> int, CL2 -> int) are indistinguishable and both can be worst conversion (user-defined conversion + promotion). Simularly for std::initializer_list<long>, but with worst conversion sequence as user-defined conversion + standard conversion. And then the main question: which conversion (for cl1 or cl2) is selected as worst? Assume that in both initializer lists the worst conversion is selected as first (for cl1). Then, according to 13.3.3.2/3.3 [over.ics.rank]
User-defined conversion sequence U1 is a better conversion sequence
than another user-defined conversion sequence U2 if they contain the
same user-defined conversion function or constructor or they
initialize the same class in an aggregate initialization and in either
case the second standard conversion sequence of U1 is better than the
second standard conversion sequence of U2.
the case with int is better because its second standard conversion sequence is better (promotion against standard conversion) and both conversions contain the same operator short(). Then assume that for std::initializer_list<long> worst conversion is for second element (cl2), and here is ambuguity because conversion functions are different.

Related

Does C++ guarantee this enum vs int constructor overload resolution?

Consider this example program:
#include <iostream>
typedef enum { A, B, C } MyEnum;
struct S
{
S(int) { std::cout << "int" << std::endl; }
S(MyEnum) { std::cout << "MyEnum" << std::endl; }
};
S f()
{
return A;
}
int main()
{
S const s = f();
}
Compiled with both clang and gcc this produces an executable that prints "MyEnum" when run. Is this behavior guaranteed by the C++ standard?
Yes, S::S(MyEnum) wins in overload resolution because it's an exact match. While S::S(int) requires one more implicit conversion (integral promotion) from enum to int.
Each type of standard conversion sequence is assigned one of three ranks:
Exact match: no conversion required, lvalue-to-rvalue conversion, qualification > conversion, function pointer conversion, (since C++17) user-defined conversion of class type to the same class
Promotion: integral promotion, floating-point promotion
Conversion: integral conversion, floating-point conversion, floating-integral conversion, pointer conversion, pointer-to-member conversion, boolean conversion, user-defined conversion of a derived class to its base
A standard conversion sequence S1 is better than a standard conversion sequence S2 if
a) S1 is a subsequence of S2, excluding lvalue transformations. The identity conversion sequence is considered a subsequence of any other conversion
b) Or, if not that, the rank of S1 is better than the rank of S2
F1 is determined to be a better function than F2 if implicit conversions for all arguments of F1 are not worse than the implicit conversions for all arguments of F2, and
there is at least one argument of F1 whose implicit conversion is better than the corresponding implicit conversion for that argument of F2
These pair-wise comparisons are applied to all viable functions. If exactly one viable function is better than all others, overload resolution succeeds and this function is called. Otherwise, compilation fails.
Yes, of course. return statement allows implicit construction and S(MyEnum) is the exact match.
Same would work with return {A};
But if you were to make S(MyEnum) explicit, then:
return A; will call S(int) as a fallback because MyEnum is implicitly convertible to integers. But this is worse overload candidate than S(MyEnum) due to the extra conversion, chosen only from necessity.
return {A}; represents copy-list initialization. It will fail because it forbids explicit constructors and implicit conversions.
return S{A}; represents direct-list initialization, it will call S(MyEnum), although it limits some implicit conversion, it does not impact this example and S(int) would be called had S(MyEnum) was removed.
return S(A); is essentially the same as return A; given the specified return type S.

In overload resolution, does selection of a function that uses the ambiguous conversion sequence necessarily result in the call being ill-formed?

The question arose while I was researching the answer to this SO question. Consider the following code:
struct A{
operator char() const{ return 'a'; }
operator int() const{ return 10; }
};
struct B {
void operator<< (int) { }
};
int main()
{
A a;
B b;
b << a;
}
The conversion of a to int can be either via a.operator char() followed by an integral promotion, or a.operator int() followed by an identity conversion (i.e., no conversion at all). The standard says that (§13.3.3.1 [over.best.ics]/p10, footnote omitted, bolding mine; all quotes are from N3936):
If several different sequences of conversions exist that each convert
the argument to the parameter type, the implicit conversion sequence
associated with the parameter is defined to be the unique conversion
sequence designated the ambiguous conversion sequence. For the
purpose of ranking implicit conversion sequences as described in
13.3.3.2, the ambiguous conversion sequence is treated as a user-defined sequence that is indistinguishable from any other
user-defined conversion sequence. If a function that uses the
ambiguous conversion sequence is selected as the best viable function,
the call will be ill-formed because the conversion of one of the
arguments in the call is ambiguous.
Here, B::operator<<(int) is the only viable candidate - and hence is the best viable candidate, even though the conversion sequence for the parameter is the ambiguous conversion sequence. According to the bolded sentence, then, the call should be ill-formed because "the conversion of one of the arguments in the call is ambiguous".
Yet no compiler that I tested (g++, clang, and MSVC) actually reports an error, which makes sense because after the function to call is selected through overload resolution, the function's "parameter (8.3.5) shall be initialized (8.5, 12.8, 12.1) with its corresponding
argument" (§5.2.2 [expr.call]/p4). This initialization is copy-initialization (§8.5 [dcl.init]/p15), and according to §8.5 [dcl.init]/p17, results in a new round of overload resolution to determine the conversion function to use:
The semantics of initializers are as follows. The destination type
is the type of the object or reference being initialized and the
source type is the type of the initializer expression. If the initializer is not a single (possibly parenthesized) expression, the
source type is not defined.
[...]
If the destination type is a (possibly cv-qualified) class type: [...]
Otherwise, if the source type is a (possibly cv-qualified) class type, conversion functions are considered. The applicable conversion
functions are enumerated (13.3.1.5), and the best one is chosen
through overload resolution (13.3). The user-defined conversion so
selected is called to convert the initializer expression into the
object being initialized. If the conversion cannot be done or is
ambiguous, the initialization is ill-formed.
[...]
And in this round of overload resolution, there is a tiebreaker in §13.3.3 [over.match.best]/p1:
a viable function F1 is defined to be a better function than another
viable function F2 if for all arguments i, ICSi(F1) is not a worse
conversion sequence than ICSi(F2), and then
for some argument j, ICSj(F1) is a better conversion sequence than ICSj(F2), or, if not that,
the context is an initialization by user-defined conversion (see 8.5, 13.3.1.5, and 13.3.1.6) and the standard conversion sequence from the return type of F1 to the destination type (i.e., the type of the
entity being initialized) is a better conversion sequence than the
standard conversion sequence from the return type of F2 to the
destination type.
(Example and remainder of the list omitted)
Since the standard conversion sequence from int to int (Exact Match rank) is better than the standard conversion sequence from char to int (Promotion rank), the first beats the second, and there should be no ambiguity - the conversion defined by operator int() will be used for the initialization, which then contradicts the sentence in §13.3.3.1 [over.best.ics]/p10 that says the function call will be ill-formed because of ambiguity.
Is there anything wrong in the above analysis, or is that sentence a bug in the standard?
When deciding the best user-defined conversion for a user-defined conversion sequence we have an overload candidate set.
§13.3.3/p1 says:
Define ICSi(F) as follows:
[...]
let ICSi(F) denote the implicit conversion sequence that converts the i-th argument in the list to the
type of the i-th parameter of viable function F. 13.3.3.1 defines the implicit conversion sequences and
13.3.3.2 defines what it means for one implicit conversion sequence to be a better conversion sequence
or worse conversion sequence than another.
Given these definitions, a viable function F1 is defined to be a better function than another viable function
F2 if for all arguments i, ICSi(F1) is not a worse conversion sequence than ICSi(F2), and then
— [...]
— the context is an initialization by user-defined conversion (see 8.5, 13.3.1.5, and 13.3.1.6) and the
standard conversion sequence from the return type of F1 to the destination type (i.e., the type of the
entity being initialized) is a better conversion sequence than the standard conversion sequence from
the return type of F2 to the destination type.
This applies since
§13.3.3.1.2/p2
2 The second standard conversion sequence converts the result of the user-defined conversion to the target
type for the sequence. Since an implicit conversion sequence is an initialization, the special rules for
initialization by user-defined conversion apply when selecting the best user-defined conversion for a user-defined
conversion sequence (see 13.3.3 and 13.3.3.1).
and therefore the conversion sequence involving operator int is selected as best match.
Finally I would rephrase §13.3.3.1/p10 as
If several different sequences of conversions exist that each convert the argument to the parameter type and it was not possible to determine a best candidate,
the implicit conversion sequence associated with the parameter is defined to be the unique conversion sequence
designated the ambiguous conversion sequence. For the purpose of ranking implicit conversion sequences
as described in 13.3.3.2, the ambiguous conversion sequence is treated as a user-defined sequence that is
indistinguishable from any other user-defined conversion sequence134. If a function that uses the ambiguous
conversion sequence is selected as the best viable function, the call will be ill-formed because the conversion
of one of the arguments in the call is ambiguous.

operator[](const char *) ambiguity

The following code
#include <string>
struct Foo {
operator double() {
return 1;
}
int operator[](std::string x) {
return 1;
}
};
int main() {
Foo()["abcd"];
}
Compiles fine with g++ but fails with clang and intel compilers because of an ambiguity between the declared method and native operator [].
It would be clear for me if Foo had an implicit conversion to int, but here the conversion is to double. Doesn't that solve the ambiguity?
§13.3.3.1.2 [over.ics.user]/p1-2:
A user-defined conversion sequence consists of an initial standard
conversion sequence followed by a user-defined conversion (12.3)
followed by a second standard conversion sequence. If the user-defined
conversion is specified by a constructor (12.3.1), the initial
standard conversion sequence converts the source type to the type
required by the argument of the constructor. If the user-defined
conversion is specified by a conversion function (12.3.2), the initial
standard conversion sequence converts the source type to the implicit
object parameter of the conversion function.
The second standard conversion sequence converts the result of the
user-defined conversion to the target type for the sequence.
In particular, there's an implicit conversion from floating point to integral type (§4.9 [conv.fpint]/p1):
A prvalue of a floating point type can be converted to a prvalue of an
integer type. The conversion truncates; that is, the fractional part
is discarded. The behavior is undefined if the truncated value cannot
be represented in the destination type.
For overload resolution purposes, the applicable candidates are:
Foo::operator[](std::string x) // overload
operator[](std::ptrdiff_t, const char *); // built-in
Given an argument list of types (Foo, const char [5]).
To match the first operator function, the first argument is an exact match; the second requires a user-defined conversion.
To match the second built-in function, the first argument requires a user-defined conversion sequence (the user-defined conversion to double followed by a standard conversion to std::ptrdiff_t, a floating-integral conversion). The second argument requires a standard array-to-pointer conversion (still exact match rank), which is better than a user-defined conversion.
Thus for the first argument the first function is better; for the second argument the second function is better, we have a criss-cross situation, overload resolution fails, and the program is ill-formed.
Note that, while for the purposes of operator overload resolution, a user-defined conversion sequence can have two standard conversion sequences (one before and one after the user-defined conversion), and operands of non-class-type can be converted to match the candidates, if a built-in operator is selected, the second standard conversion sequence is not applied for operands of class type, and no conversion at all is applied for operands for non-class type before the operator is interpreted as a built-in (§13.3.1.2 [over.match.oper]/p7):
If a built-in candidate is selected by overload resolution, the
operands of class type are converted to the types of the corresponding
parameters of the selected operation function, except that the second
standard conversion sequence of a user-defined conversion sequence
(13.3.3.1.2) is not applied. Then the operator is treated as the
corresponding built-in operator and interpreted according to Clause 5.
Thus if Foo::operator[](std::string x) is removed, the compiler should report an error, though clang doesn't. This is an obvious clang bug, as it fails to reject the example given in the standard.

Given the following code (in GCC 4.3) , why is the conversion to reference called twice?

Given the following code (in GCC 4.3) , why is the conversion to reference called in both cases?
class A { };
class B {
public:
operator A() {}
operator A&() {}
};
int main() {
B b;
(A) b;
(A&) b;
}
http://ideone.com/d6iF8
Your code is ambiguous and should not compile (it is ill-formed per 13.3.3:2).
lvalue-to-rvalue conversion has the same rank as identity conversion, so (per 13.3.3:1) there is no way to choose between them.
Comeau C++ (probably the most standards-compliant compiler) gives the following error:
"ComeauTest.c", line 11: error: more than one user-defined conversion from "B" to
"A" applies:
function "B::operator A()"
function "B::operator A &()"
(A) b;
^
Here's the relevant text from the standard:
c++11
13.3.3 Best viable function [over.match.best]
[...] Given these definitions, a viable function F1 is defined to be a better function than another viable function F2 [...]
2 -
If there is exactly one viable function that is a better function than all other viable functions, then it is the
one selected by overload resolution; otherwise the call is ill-formed.
The definitions themselves are complicated, but there's two things to note with user-defined conversions:
First, the application of user-defined conversion as a conversion sequence is specified to decompose into a sequence S_a - U - S_b of a standard conversion sequence followed by a user-defined conversion followed by another standard conversion sequence. This covers all the cases; you can't have more than one user-defined conversion in a conversion sequence, and a standard conversion sequence can be the "identity conversion" i.e. no conversion required.
Second, when comparing user-defined conversion sequences the only part that matters is the second standard conversion sequence. This is in 13.3.3:
c++11
13.3.3 Best viable function [over.match.best]
[...] a viable function F1 is defined to be a better function than another viable function
F2 if [...]
the context is an initialization by user-defined conversion (see 8.5, 13.3.1.5, and 13.3.1.6) and the
standard conversion sequence from the return type of F1 to the destination type (i.e., the type of the
entity being initialized) is a better conversion sequence than the standard conversion sequence from
the return type of F2 to the destination type.
and in 13.3.3.2:
c++11
13.3.3.2 Ranking implicit conversion sequences [over.ics.rank]
3 - Two implicit conversion sequences of the same form are indistinguishable conversion sequences unless one of
the following rules applies: [...]
User-defined conversion sequence U1 is a better conversion sequence than another user-defined conversion sequence U2 if they contain the same user-defined conversion function or constructor or aggregate
initialization and the second standard conversion sequence of U1 is better than the second standard
conversion sequence of U2.
So when comparing conversion sequences U1 = (S1_a - U'1 - S1_b) and U2 = (S2_a - U'2 - S2_b) the only thing that matters is the relative rank of S1_b and S2_b; the standard conversion sequences required to arrive at the parameter of the user-defined conversions do not matter.
So the possible conversion sequences for (A) b, requiring a conversion sequence yielding B -> A, are:
U1: B -> B [identity], B::operator A() [user-defined], A -> A [identity]
U2: B -> B [identity], B::operator A &() [user-defined], A & -> A [rvalue-to-lvalue]
Now, how do we rank standard conversion sequences? The place to look is table 12 in 13.3.3.1.1, which specifies that lvalue-to-rvalue conversion has the same rank ("Exact Match") as identity conversion. So the two user-defined conversion sequences cannot be distinguished, and the program is ill-formed.
Sidebar
What's the difference between 13.3.3 and 13.3.3.2 as regards ranking user-defined conversion sequences?
13.3.3 allows the compiler to distinguish between different user-defined conversion operators; 13.3.3.2 allows the compiler to distinguish between different functions that each require a user-defined conversion in their arguments.
So, in the code
struct A {
operator int();
operator float();
} a;
void f(int);
f(a);
13.3.3 applies and A::operator int() is selected over A::operator float(); in the code
struct A {
operator int();
} a;
void f(int);
void f(double);
f(a);
13.3.3.2 applies and void f(int) is selected over void f(double). However in the code
struct A {
operator int();
operator float();
} a;
void f(int);
void f(double);
f(a);
even though 13.3.3 prefers A::operator int() -> void f(int) over A::operator float() -> void f(int) and float -> double over int -> double, and 13.3.3.2 prefers int -> int over int -> double and float -> double over float -> int, there is no way to distinguish between the int -> int and float -> double conversion sequences (because they contain neither the same user-defined conversion operator nor the same overload of f), and so the code is ill-formed.

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

The standard appears to provide two rules for distinguishing between implicit conversion sequences that involve user-defined conversion operators:
c++11
13.3.3 Best viable function [over.match.best]
[...] a viable function F1 is defined to be a better function than another viable function
F2 if [...]
the context is an initialization by user-defined conversion (see 8.5, 13.3.1.5, and 13.3.1.6) and the
standard conversion sequence from the return type of F1 to the destination type (i.e., the type of the
entity being initialized) is a better conversion sequence than the standard conversion sequence from
the return type of F2 to the destination type.
13.3.3.2 Ranking implicit conversion sequences [over.ics.rank]
3 - Two implicit conversion sequences of the same form are indistinguishable conversion sequences unless one of
the following rules applies: [...]
User-defined conversion sequence U1 is a better conversion sequence than another user-defined conversion sequence U2 if they contain the same user-defined conversion function or constructor or aggregate
initialization and the second standard conversion sequence of U1 is better than the second standard
conversion sequence of U2.
As I understand it, 13.3.3 allows the compiler to distinguish between different user-defined conversion operators, while 13.3.3.2 allows the compiler to distinguish between different functions (overloads of some function f) that each require a user-defined conversion in their arguments (see my sidebar to Given the following code (in GCC 4.3) , why is the conversion to reference called twice?).
Are there any other rules that can distinguish between user-defined conversion sequences? The answer at https://stackoverflow.com/a/1384044/567292 indicates that 13.3.3.2:3 can distinguish between user-defined conversion sequences based on the cv-qualification of the implicit object parameter (to a conversion operator) or of the single non-default parameter to a constructor or aggregate initialisation, but I don't see how that can be relevant given that that would require comparison between the first standard conversion sequences of the respective user-defined conversion sequences, which the standard doesn't appear to mention.
Supposing that S1 is better than S2, where S1 is the first standard conversion sequence of U1 and S2 is the first standard conversion sequence of U2, does it follow that U1 is better than U2? In other words, is this code well-formed?
struct A {
operator int();
operator char() const;
} a;
void foo(double);
int main() {
foo(a);
}
g++ (4.5.1), Clang (3.0) and Comeau (4.3.10.1) accept it, preferring the non-const-qualified A::operator int(), but I'd expect it to be rejected as ambiguous and thus ill-formed. Is this a deficiency in the standard or in my understanding of it?
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.