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

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.

Related

Why does bool(val) prefer double implicit conversions over val.operator bool()?

The piece of code below dereferences a nullptr.
struct Foo {
int *bar;
operator int&() {
return *bar;
}
explicit operator bool() const {
return bar;
}
};
int main() {
Foo f {nullptr};
auto _ = bool(f);
}
Why does bool(f) call bool(f.operator int&()) and not f.operator bool() as was intended?
Is there a way to make bool(f) call f.operator bool() as intended without marking operator int& as explicit?
Argument conversion ranking takes precedence over return type conversion ranking in overload resolution for user-defined conversions
All standard references below refers to N4659: March 2017 post-Kona working draft/C++17 DIS.
Preparations
To avoid having to deal with segfaults, auto type deduction and consideration of explicit marked conversion functions, consider the following simplified variation of your example, which shows the same behaviour:
#include <iostream>
struct Foo {
int bar{42};
operator int&() {
std::cout << __PRETTY_FUNCTION__;
return bar;
}
operator bool() const {
std::cout << __PRETTY_FUNCTION__;
return true;
}
};
int main() {
Foo f {};
// (A):
bool a = f; // Foo::operator int&()
}
TLDR
Why does bool(f) call bool(f.operator int&()) and not f.operator bool() as was intended?
The viable candidate functions to the initialization conversion sequence are
operator int&(Foo&)
operator bool(const Foo&)
and [over.match.best]/1.3, ranking on function arguments, takes precedence over [over.match.best]/1.4, ranking on conversion from return type, meaning operator int&(Foo&) will be chosen as it is a non-ambiguous perfect match, for an argument of type Foo&, by the [over.match.best]/1.3 rule, whereas operator bool(const Foo&) is not.
In this regard, as we are relying on [over.match.best]/1.3, it is no different than simply overloading solely on const-qualification:
#include <iostream>
struct Foo {};
void f(Foo&) { std::cout << __PRETTY_FUNCTION__ << "\n"; }
void f(const Foo&) { std::cout << __PRETTY_FUNCTION__ << "\n"; }
int main() {
Foo f1 {};
const Foo f2{};
f(f1); // void f(Foo&)
f(f2); // void f(const Foo&)
}
Is there a way to make bool(f) call f.operator bool() as intended without marking operator int& as explicit?
As per above, if you provide matching cv-qualifiers for the member function overloads, there can no longer be any differentiation on the implicit object argument as per [over.match.best]/1.3, and the bool conversion function will be chosen as most viable as per [over.match.best]/1.4. Note that by marking the int& conversion functions as explicit, it will no longer be a viable candidate, and the choice for the bool conversion function will not be due to it being the most viable overload, but by it being the only viable overload.
Details
The expression at (A) is initialization, with semantics governed specifically by [dcl.init]/17.7 [extract, emphasis mine]:
[dcl.init]/17 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.
[...]
/17.7 Otherwise, if the source type is a (possibly cv-qualified) class type, conversion functions are considered. The applicable
conversion functions are enumerated ([over.match.conv]), and the best
one is chosen through overload resolution. The user-defined conversion
so selected is called to convert the initializer expression into the
object being initialized. [...]
where [over.match.conv]/1 describes which conversion functions that are considered candidate functions in overload resolution:
[over.match.conv]/1 Under the conditions specified in [dcl.init], as part of an initialization of an object of non-class type, a conversion function can be invoked to convert an initializer expression of class type to the type of the object being initialized. Overload resolution is used to select the conversion function to be invoked. Assuming that “cv1 T” is the type of the object being initialized, and “cv S” is the type of the initializer expression, with S a class type, the candidate functions are selected as follows:
/1.1 The conversion functions of S and its base classes are considered. Those non-explicit conversion functions that are not
hidden within S and yield type T or a type that can be converted
to type T via a standard conversion sequence are candidate
functions. [...] Conversion functions that return “reference to cv2
X” return lvalues or xvalues, depending on the type of reference, of
type “cv2 X” and are therefore considered to yield X for this
process of selecting candidate functions.
In this example, cv T, the type of the object being initialized, is bool, and thus both used-defined conversion functions are viable candidates, as one directly yields type bool and the other yields a type that can be converted to type bool via a standard conversion sequence (int to bool); as per [conv.bool]:
A prvalue of arithmetic, unscoped enumeration, pointer, or pointer to member type can be converted to a prvalue of type bool. [...]
Moreover, the type of the initializer expression is Foo, and [over.match.funcs]/4 governs that the cv-qualification of the type of the implicit object parameter for user-defined conversion functions is that of the cv-qualification of the respective function:
For non-static member functions, the type of the implicit object
parameter is
“lvalue reference to cv X” for functions declared without a ref-qualifier or with the & ref-qualifier
[...]
where X is the class of which the function is a member and cv is
the cv-qualification on the member function declaration. [...] For
conversion functions, the function is considered to be a member of the
class of the implied object argument for the purpose of defining the
type of the implicit object parameter. [...]
Thus, w.r.t. overload resolution we may summarize as follows:
// Target type: bool
// Source type: Foo
// Viable candidate functions:
operator int&(Foo&)
operator bool(const Foo&)
where we have added the implied object parameter as explicit function parameter, without loss of generality (as per [over.match.funcs]/5), when continuing for how overload resolution picks the best viable candidate.
Now, [over.ics.user], particularly [over.ics.user]/2 summarizes this:
[over.ics.user]/2 [...] 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 [over.match.best] and [over.best.ics]).
particularly that the rules for selecting the best viable candidate is governed by [over.match.best], particularly [over.match.best]/1:
[over.match.best]/1 [...] 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
/1.3 for some argument j, ICSj(F1) is a better conversion sequence than ICSj(F2), or, if not that,
/1.4 the context is an initialization by user-defined conversion (see [dcl.init], [over.match.conv], and [over.match.ref])
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
The key here is that [over.match.best]/1.4, regarding conversion on the return type of the candidate (to the target type) only applies if the overloads cannot be disambiguated by means of [over.match.best]/1.3. In our example, however, recall that the viable candidate functions are:
operator int&(Foo&)
operator bool(const Foo&)
As per [over.ics.rank]/3.2, particularly [over.ics.rank]/3.2.6:
[over.ics.rank]/3 Two implicit conversion sequences of the same form are indistinguishable conversion sequences unless one of the
following rules applies:
[...]
/3.2 Standard conversion sequence S1 is a better conversion sequence than standard conversion sequence S2 if
[...]
/3.2.6 S1 and S2 are reference bindings ([dcl.init.ref]), and the types to which the references refer are the same type
except for top-level cv-qualifiers, and the type to which the
reference initialized by S2 refers is more cv-qualified than the
type to which the reference initialized by S1 refers.
meaning, that for an argument of type Foo&, operator int&(Foo&) will be a better (/1.3: exact) match, whereas for e.g. an argument of type const Foo&, operator bool(const Foo&) will the only match (Foo& will not be viable).

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.

Should initialization by conversion function be ambiguous when two candidates have the same cv-qualification?

Both clang and gcc accept the following code and choose A::operator B*.
struct B
{
};
struct A : B
{
operator A*();
operator B*();
};
A a;
void* x = a;
My reading of the standard - specifically sentences highlighted below in bold - suggests that this conversion should be ambiguous.
Both A::operator A* and A::operator B* are candidates for overload resolution because A* and B* are both convertible to void* via a standard conversion. Because the implied object parameter A& is the only argument, only the conversion sequence that converts from the implied object argument to the implied object parameter is considered - the type yielded by the conversion function is ignored. In both cases, the implied object argument is the initializer expression's type A, and the implied object parameter is A&. If both conversion sequences are identical, there is no way to distinguish between the two candidates.
8.5 Initializers [dcl.init]
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 destination type is a [reference/array/class...] [deleted details not applicable to this scenario]
— 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.
13.3.1.5 Initialization by conversion function [over.match.conv]
Under the conditions specified in 8.5, as part of an initialization of an object of nonclass type, a conversion
function can be invoked to convert an initializer expression of class type to the type of the object being
initialized. Overload resolution is used to select the conversion function to be invoked. Assuming that “cv1
T” is the type of the object being initialized, and “cv S” is the type of the initializer expression, with S a
class type, the candidate functions are selected as follows:
— The conversion functions of S and its base classes are considered. Those non-explicit conversion
functions that are not hidden within S and yield type T or a type that can be converted to type T
via a standard conversion sequence (13.3.3.1.1) are candidate functions. For direct-initialization, those
explicit conversion functions that are not hidden within S and yield type T or a type that can be
converted to type T with a qualification conversion (4.4) are also candidate functions. Conversion
functions that return a cv-qualified type are considered to yield the cv-unqualified version of that type
for this process of selecting candidate functions. Conversion functions that return “reference to cv2
X” return lvalues or xvalues, depending on the type of reference, of type “cv2 X” and are therefore
considered to yield X for this process of selecting candidate functions.
The argument list has one argument, which is the initializer expression. [ Note: This argument will be
compared against the implicit object parameter of the conversion functions. —end note ]
Is this ambiguous according to the standard?
EDIT: note that this is a similar question, but not the same as Distinguishing between user-defined conversion sequences by the initial standard conversion sequence
The difference being that in my example both conversion functions have the same qualification.
TLDR: When everything else is equal, overload resolution breaks the tie by which conversion function has the best conversion from its return value to the target type.
All references are to ISO/IEC 14882:2011 (C++11). The behavior of the initialization:
void* x = a;
is defined as follows. First, this is an initialization as described in 8.5 Initializers [dcl.init] and conforms to the grammar described in p1. Since the destination type void* is a non-class type, and the source type A is a class type, this specific initializer is of the form described in 8.5 p16, bullet 7:
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.
The "enumeration of applicable conversion functions" is detailed in 13.3.1.5 p1:
Under the conditions specified in 8.5, as part of an initialization of an object of nonclass type, a conversion
function can be invoked to convert an initializer expression of class type to the type of the object being
initialized. Overload resolution is used to select the conversion function to be invoked. Assuming that “cv1
T” is the type of the object being initialized, and “cv S” is the type of the initializer expression, with S a
class type, the candidate functions are selected as follows:
The conversion functions of S and its base classes are considered. Those non-explicit conversion
functions that are not hidden within S and yield type T or a type that can be converted to type T
via a standard conversion sequence (13.3.3.1.1) are candidate functions. For direct-initialization, those
explicit conversion functions that are not hidden within S and yield type T or a type that can be
converted to type T with a qualification conversion (4.4) are also candidate functions. Conversion
functions that return a cv-qualified type are considered to yield the cv-unqualified version of that type
for this process of selecting candidate functions. Conversion functions that return “reference to cv2
X” return lvalues or xvalues, depending on the type of reference, of type “cv2 X” and are therefore
considered to yield X for this process of selecting candidate functions.
Note that both A::operator A*() and A::operator B*() are candidate functions, since both A* and B* are convertible to void* per
4.10p2: "A prvalue of type “pointer to cv T,” where T is an object type, can be converted to a prvalue of type “pointer
to cv void”." Given that both functions are candidates, overload resolution must choose between them.
Overload resolution is decribed in 13.3 [over.match]. p2 states:
Overload resolution selects the function to call in seven distinct contexts within the language:
...
invocation of a conversion function for initialization of an object of a nonclass type from an expression of class type (13.3.1.5)
...
Each of these contexts defines the set of candidate functions and the list of arguments in its own unique way. But, once the candidate functions and argument lists have been identified, the selection of the best function is the same in all cases:
First, a subset of the candidate functions (those that have the proper number of arguments and meet certain other conditions) is selected to form a set of viable functions (13.3.2).
Then the best viable function is selected based on the implicit conversion sequences (13.3.3.1) needed to match each argument to the corresponding parameter of each viable function.
Which of our two functions are viable? 13.3.2 [over.match.viable] p1:
From the set of candidate functions constructed for a given context (13.3.1), a set of viable functions is
chosen, from which the best function will be selected by comparing argument conversion sequences for the
best fit (13.3.3).
The requirements are presented in p2:
First, to be a viable function, a candidate function shall have enough parameters to agree in number with
the arguments in the list.
and p3:
Second, for F to be a viable function, there shall exist for each argument an implicit conversion sequence
(13.3.3.1) that converts that argument to the corresponding parameter of F.
Both requirements are trivially met by our conversion functions: they have a single (implicit) argument of the same type as the initializer expression a.
Determination of the best of the viable functions is described in 13.3.3 [over.match.best]. It defines some formalisms for describing conversion sequences, sequences of operations necessary to convert from the types of the actual function arguments to the types of the formal function parameters. In the case of our conversion functions, they both have exactly one parameter whose type is exactly that of the actual argument, so the "conversion sequence" corresponding to each overload is the identity sequence. They are discriminated by the language in p1:
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
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.
What about that final bullet? Does one of our overloads have a better standard conversion sequence from its return type to void*?
13.3.3.2 Ranking Implicit Conversion Sequences [over.ics.rank] p4 states in the second bullet point:
If class B is derived directly or indirectly from class A, conversion of B* to A* is better than conversion of B* to void*, and conversion of A* to void* is better than conversion of B* to void*.
This is exactly the case of the OP, except with the names A and B reversed. Overload resolution on the two conversion operators of the OP is resolved in favor of A::operator B*() since the cited rule makes the conversion sequence B* → void* better than A* → void*

Overload resolution and arrays: which function should be called?

Consider the following program:
#include <cstddef>
#include <cstdio>
void f(char const*&&) { std::puts("char const*&&"); } // (1)
void f(char const* const&) { std::puts("char const* const&"); } // (2)
template <std::size_t N>
void f(char const (&)[N]) { std::puts("char const(&)[N]"); } // (3)
int main()
{
const char data[] = "a";
f(data);
}
Which f should be called? Why?
The latest released versions of three compilers disagree on the answer to this question:
(1) is called when the program is compiled using g++ 4.5.2
(2) is called when the program is compiled using Visual C++ 2010 SP1
(3) is called when the program is compiled using Clang 3.0 (trunk 127530)
Have the overload resolution rules changed substantially in different C++0x drafts? Or, are two of these compilers really just completely wrong? Which overload is the correct overload to be selected per the latest C++0x draft?
First, the conversion sequence of all three is the same, except that for the first two, there is an lvalue transformation (lvalue to rvalue conversion), which however is not used in ordering conversion sequences. All three are exact matches (the function template specialization has parameter type char const(&)[2]).
If you iterate over the rules at 13.3.3.2p3, you stop at this paragraph
S1 and S2 are reference bindings (8.5.3) and neither refers to an implicit object parameter of a non-static member function declared without a ref-qualifier, and S1 binds an rvalue reference to an rvalue and S2 binds an lvalue reference.
A conversion sequence cannot be formed if it requires binding an rvalue reference to an lvalue, the spec says at 13.3.3.1.4p3. If you look at how reference binding works at 8.5.3p5 last bullet, it will create a temporary (I think they meant rvalue temporary) of type char const* from the array lvalue and bind the reference to that temporary. Therefor, I think (1) is better than (2). Same holds for (1) against (3), although we wouldn't need this because (3) is a template so in a tie, we would choose (1) again.
In n3225, they changed the reference binding rules so that rvalue references can bind to initializer expressions that are lvalues, as long as the reference will be bound to an rvalue (possibly created by converting the initializer properly before). This could influence the handling by Visual C++, which may not be up to date here.
I'm not sure about clang. Even if it would ignore (1), then it would end up in a tie between (2) and (3), and would need to choose (2) because it's a non-template.
I think that 8.5.3p5 last bullet is confusing because it says "Otherwise a temporary of type ..". It's not clear whether the temporary is regarded as an lvalue or as an rvalue by 13.3.3.1.4p3, which means I'm not sure how the following should really behave according to the exact words of the spec
void f(int &);
void f(int &&);
int main() {
int n = 0;
f(n);
}
If we assume the temporary is treated as an rvalue by clause 13, then we bind an rvalue ref to an rvalue in the second function and an lvalue in the first. Therefor, we will choose the second function and then get a diagnostic by 8.5.3p5 last bullet because T1 and T2 are reference-related. If we assume the temporary is treated as an lvalue by clause 13, then the following would not work
void f(int &&);
int main() {
f(0);
}
Because we would bind an rvalue ref to an lvalue which by clause 13 will make the function non-viable. And if we interpret "binding an rvalue ref to an lvalue" to refer to the initializer expression instead of the final expression bound to, we won't accept the following
void f(float &&);
int main() {
int n = 0;
f(n);
}
This however is valid as of n3225. So there seems to be some confusion - I sent a DR to the committee about this.
I claim that #3 is the function chosen by a conforming compiler.
(1) is better than (2) because "Standard conversion sequence S1 is a better conversion sequence than standard conversion sequence S2 if S1 and S2 are reference bindings (8.5.3) and neither refers to an implicit object parameter of a non-static member function declared without a ref-qualifier, and S1 binds an rvalue reference to an rvalue and S2 binds an lvalue reference."
(3) is better than both (1) and (2) because it is an identity conversion (the others are exact match conversions) and "Standard conversion sequence S1 is a better conversion sequence than standard conversion sequence S2 if S1 is a proper subsequence of S2 (comparing the conversion sequences in the canonical form defined by 13.3.3.1.1, excluding any Lvalue Transformation; the identity conversion sequence is considered to be a subsequence of any non-identity conversion sequence)"
Template vs non-template is only considered when neither conversion is better "or, if not that..."
oddly enough though, Comeau prefers (2) over (3). This test case fails to compile:
#include <cstddef>
#include <cstdio>
// (1) removed because Comeau doesn't support rvalue-references yet
char f(char const* const&) { std::puts("char const* const&"); return 0; } // (2)
template <std::size_t N>
int f(char const (&)[N]) { std::puts("char const(&)[N]"); return 0; } // (3)
int main()
{
const char data[] = "a";
switch (0) {
case sizeof(char):
break;
case sizeof(f(data)):
break;
}
}
This is a community wiki answer for collecting snippets from the standard (draft 3225).
section 13.3.3 "Best viable function" [over.match.best]
Define ICSi(F) as follows:
if F is a static member function, ICS1(F) is defined such that ICS1(F) is neither better nor worse than
ICS1(G) for any function G, and, symmetrically, ICS1(G) is neither better nor worse than ICS1(F); otherwise,
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
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
or, if not that,
F1 is a non-template function and F2 is a function template specialization
or, if not that,
F1 and F2 are function template specializations, and the function template for F1 is more specialized
than the template for F2 according to the partial ordering rules described in 14.5.6.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.
section 13.3.3.1.4 "Reference binding" [over.ics.ref]
When a parameter of reference type binds directly (8.5.3) to an argument expression, the implicit conversion
sequence is the identity conversion, unless the argument expression has a type that is a derived class of the
parameter type, in which case the implicit conversion sequence is a derived-to-base conversion (13.3.3.1). If the parameter binds directly to the result of applying a conversion function to the
argument expression, the implicit conversion sequence is a user-defined conversion sequence (13.3.3.1.2), with the second standard conversion sequence either an identity conversion or, if the conversion function
returns an entity of a type that is a derived class of the parameter type, a derived-to-base Conversion.
When a parameter of reference type is not bound directly to an argument expression, the conversion sequence
is the one required to convert the argument expression to the underlying type of the reference according
to 13.3.3.1. Conceptually, this conversion sequence corresponds to copy-initializing a temporary of the
underlying type with the argument expression. Any difference in top-level cv-qualification is subsumed by
the initialization itself and does not constitute a conversion.
section 13.3.3.2 "Ranking implicit conversion sequences" [over.ics.rank]
13.3.3.2 defines a partial ordering of implicit conversion sequences based on the relationships better conversion
sequence and better conversion. If an implicit conversion sequence S1 is defined by these rules to be a better
conversion sequence than S2, then it is also the case that S2 is a worse conversion sequence than S1. If
conversion sequence S1 is neither better than nor worse than conversion sequence S2, S1 and S2 are said to
be indistinguishable conversion sequences.
When comparing the basic forms of implicit conversion sequences (as defined in 13.3.3.1)
a standard conversion sequence (13.3.3.1.1) is a better conversion sequence than a user-defined conversion sequence or an ellipsis conversion sequence, and
a user-defined conversion sequence (13.3.3.1.2) is a better conversion sequence than an ellipsis conversion sequence (13.3.3.1.3).
Two implicit conversion sequences of the same form are indistinguishable conversion sequences unless one of
the following rules applies:
Standard conversion sequence S1 is a better conversion sequence than standard conversion sequence S2 if
S1 is a proper subsequence of S2 (comparing the conversion sequences in the canonical form defined by 13.3.3.1.1, excluding any Lvalue Transformation; the identity conversion sequence is considered to be a subsequence of any non-identity conversion sequence)
or, if not that,
the rank of S1 is better than the rank of S2, or S1 and S2 have the same rank and are distinguishable by the rules in the paragraph below
or, if not that,
S1 and S2 differ only in their qualification conversion and yield similar types T1 and T2 (4.4), respectively, and the cv-qualification signature of type T1 is a proper subset of the cv-qualification signature of type T2.
or, if not that,
S1 and S2 are reference bindings (8.5.3) and neither refers to an implicit object parameter of a
non-static member function declared without a ref-qualifier, and S1 binds an rvalue reference to
an rvalue and S2 binds an lvalue reference.