Implicit conversion sequences? - c++

N3797 §13.3.3.1 [over.best.ics] defines an implicit conversion sequence concept. More precisely, it says:
An implicit conversion sequence is a sequence of conversions used to
convert an argument in a function call to the type of the
corresponding parameter of the function being called.
The sequence of conversions is an implicit conversion as defined in
Clause 4, which means it is governed by the rules for initialization
of an object or reference by a single expression (8.5, 8.5.3).
The thing is Clause 4 doesn't concerned in user-defined conversions and ellipsis conversions, it only defines standard conversion. Since, the sentence The sequence of conversions is an implicit conversion as defined in Clause 4 isn't clear to me. How can the rules from the clause 4 ever be applied to all three conversion sequences. I mean
A well-formed implicit conversion sequence is one of the following
forms:
— a standard conversion sequence (13.3.3.1.1),
— a user-defined conversion sequence (13.3.3.1.2), or
— an ellipsis conversion sequence (13.3.3.1.3).

Related

Are standard conversion sequences include explicit conversions?

I am just trying to understand what does the standard mean by "standard conversion sequences"; and I have ended up with that "standard conversion sequences" are "sequences of standard implicit conversions". But I think that's not true for some contexts; for instance, from [expr.static.cast]/7:
[..] A program is ill-formed if it uses static_­cast to perform the inverse of an ill-formed standard conversion sequence.
struct B { };
struct D : private B { };
void f() {
static_cast<D*>((B*)0); // error: B is a private base of D
// ..
}
And General[conv.general]/1 states:
Standard conversions are implicit conversions with built-in meaning.
[..] A standard
conversion sequence is a sequence of standard conversions in the
following order:
[..]
(1.2) Zero or one conversion from the
following set: integral promotions, floating-point promotion, integral
conversions, floating-point conversions, floating-integral
conversions, pointer conversions, pointer-to-member conversions, and
boolean conversions.
[..]
As I know, I think that a standard conversion sequence is only implicit conversions not including any explicit conversion. I mean the above conversion (B*)0 is explicit pointer conversion, even though the standard said that this conversion is ill-formed standard conversion sequance.
So if my thinking is true, why is this explicit cast expression (B*)0 is said to be standard conversion sequence and it is an implicit conversion not explicit?
From this answer on a some question:
the standard conversion is a set of built-in rules the compiler can
apply when converting one type to another. Those built-in conversions
include:
No conversions
Lvalue-to-rvalue conversion
Array-to-pointer conversion
Function-to-pointer conversion
Qualification conversions
Integral promotions
Floating point promotion
Integral conversions
Floating point conversions
Floating-integral conversions
Pointer conversions
Pointer to member conversions
Boolean conversions
Given the conversions above, if those conversions are performed explicitly, do they still said to be standard conversion sequences?
In general, Are conversions performed explicitly (including C++ cast operators) said to be standard conversion sequences?

Implicit conversion sequence

N3797 §13.3.3.1 [over.best.ics] says:
The sequence of conversions is an implicit conversion as defined in
Clause 4 [...]
However, clause 4 defines the following list of the conversions:
Lvalue-to-rvalue conversion
Array-to-pointer conversion
Function-to-pointer conversion
Qualification conversions
Integral promotions
Floating point promotion
Integral conversions
Floating point conversions
Floating-integral conversions
Pointer conversions
Pointer to member conversions
Boolean conversions
Integer conversion rank
Consider the following example:
#include <iostream>
using namespace std;
struct A
{
operator int()
{
return 42;
}
};
A a;
int b = a; //User-defined conversion sequence applied
int main() { }
As long as user-defined conversion doesn't belong to a set of standard conversions, there is no any standard conversion being applied in the example. So what is the sense of the quote I provided?
The rest of the quote you omitted might be illuminating:
§13.3.3.1/1 An implicit conversion sequence is a sequence of
conversions used to convert an argument in a function call to the type
of the corresponding parameter of the function being called. The
sequence of conversions is an implicit conversion as defined in Clause
4, which means it is governed by the rules for initialization of an
object or reference by a single expression (8.5, 8.5.3).
Clause 4 does indeed talk about this.
3 An expression e can be implicitly converted to a type T if and
only if the declaration T t=e; is well-formed, for some invented
temporary variable t (8.5).
6 The effect of any implicit conversion is the same as performing the
corresponding declaration and initialization and then using the
temporary variable as the result of the conversion. The result is an
lvalue if T is an lvalue reference type or an rvalue reference to
function type (8.3.2), an xvalue if T is an rvalue reference to
object type, and a prvalue otherwise. The expression e is used as a
glvalue if and only if the initialization uses it as a glvalue.
The "full set of such conversions" (listed in Clause 4) refers to standard conversions. Remember that it says standard conversion sequences can be empty. Then §13.3.3.1.2 describes user-defined conversion sequences. It consists of:
A standard conversion sequence
A user-defined conversion
Another standard conversion sequence

Second standard conversion sequence of user-defined conversion

I have a misunderstanding about standard-conversion sequence terms. I have come across the following quote N3797 §8.5.3/5 [dcl.init.ref]:
— If the initializer expression
— is an xvalue (but not a bit-field), class prvalue, array prvalue or
function lvalue and “cv1 T1” is reference-compatible with “cv2
T2”, or
— has a class type (i.e., T2 is a class type), where T1 is not
reference-related to T2, and can be converted to an xvalue, class
prvalue, 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 user-defined conversion
sequence includes an lvalue-to-rvalue conversion, the program is
ill-formed.
What is the second standard conversion sequence here? I thought there is a standard conversion sequence including all necessary standard conversions (user-defined and implicit).
[over.ics.user]:
A user-defined conversion consists of an initial standard conversion sequence followed by a user-defined conversion (12.3) followed by a second standard conversion sequence. […]
The second standard conversion sequence converts the result of the
user-defined conversion to the target type for the sequence.
E.g. for
struct A
{
operator int();
};
void foo(short);
foo(A());
The second standard conversion sequence converts the int prvalue to the parameter of foo, that is, short. The first standard conversion sequence converts the A object to A (the implicit object parameter of operator int), which constitutes an identity conversion. For references, the rule quoted by you 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&
Here, operator int& is selected by overload resolution. The return value is an lvalue reference to int. For that to initialize the reference, an lvalue-to-rvalue conversion would be necessary, and that's precisely what the quote prevents: Lvalues shall not be bound to rvalue references.
What the standard conversion term means is covered in the following clause of the C++ Standard:
4 Standard conversions [conv]
Standard conversions are implicit conversions with built-in meaning. Clause 4 enumerates the full set of such conversions. A standard conversion sequence is a sequence of standard conversions in the following order:
— Zero or one conversion from the following set: lvalue-to-rvalue conversion, array-to-pointer conversion,
and function-to-pointer conversion.
— Zero or one conversion from the following set: integral promotions, floating point promotion, integral conversions, floating point conversions, floating-integral conversions, pointer conversions, pointer to member conversions, and boolean conversions.
— Zero or one qualification conversion.
[ Note: A standard conversion sequence can be empty, i.e., it can consist of no conversions. — end note ]
A standard conversion sequence will be applied to an expression if necessary to convert it to a required
destination type.
In other words, the standard conversion is a set of built-in rules the compiler can apply when converting one type to another. Those built-in conversions include:
No conversions
Lvalue-to-rvalue conversion
Array-to-pointer conversion
Function-to-pointer conversion
Qualification conversions
Integral promotions
Floating point promotion
Integral conversions
Floating point conversions
Floating-integral conversions
Pointer conversions
Pointer to member conversions
Boolean conversions
The standard conversion sequence can appear twice during the user-defined conversion sequence - either before and/or after the user-defined conversion:
§ 13.3.3.1.2 User-defined conversion sequences [over.ics.user]
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. 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).
Having that said, for the following conversion:
A a;
B b = a;
the compiler will search for the conversion constructor in B that can take an instance of A (source type) through some initial standard conversion sequence so that it could then perform that user-defined conversion through selected constructor, and then apply another standard conversion - second standard conversion - for converting the resultant type of the user-defined conversion to the target type;
or:
the compiler will search for the conversion function in A that is callable after some initial standard conversion sequence of the implicit context, that could then convert an instance of A to some type convertible through another standard conversion - the second standard conversion - to the target type B.
As a tangible example let's consider the below conversion:
struct A
{
operator int() const;
};
A a;
bool b = a;
The compiler considers the following user-defined conversion sequence:
Initial standard conversion: Qualification conversion of A* to const A* to call const-qualified operator int() const.
User-defined conversion: conversion of A to int, through user-defined conversion function.
Second standard conversion: Boolean conversion of int to bool.
The case you are asking about can be split as follows:
struct A
{
operator int&();
};
int&& b = A();
The source type is A.
The target type is int&&.
The user-defined conversion sequence is the conversion of A to int&&.
The initial standard conversion sequence is No conversion at all.
The user-defined conversion is the conversion of A to int&.
The second standard conversion sequence (converting the result of the user-defined conversion to the target type) that is a part of the overall user-defined conversion sequence would be here the standard conversion of int& to int&& - an Lvalue-to-rvalue conversion. That conversion is considered since int& and int&& are reference-compatible types. According to the below statement §8.5.3 [dcl.init.ref]/p5:
[...] if the reference is an rvalue reference and the second standard conversion sequence of the user-defined conversion sequence includes an lvalue-to-rvalue conversion, the program is ill-formed.
that conversion is not applicable in the overall user-defined conversion sequence.

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.