struct Y { Y(int); }; struct A { operator int(); }; Y y1 = A(); // error: A::operator int() is not a candidate struct X { }; struct B { operator X(); }; B b; X x({b}); // error: B::operator X() is not a candidate
class B; class A { A (B&);}; class B { operator A (); }; class C { C (B&); }; void f(A) { } void f(C) { } B b; f(b); // ill-formed: ambiguous because there is a conversion b → C (via constructor) // and an (ambiguous) conversion b → A (via constructor or conversion function) void f(B) { } f(b); // OK, unambiguous
Conversion | Category | Rank | Subclause |
No conversions required | Identity | ||
Lvalue-to-rvalue conversion | |||
Array-to-pointer conversion | Lvalue Transformation | ||
Function-to-pointer conversion | Exact Match | ||
Qualification conversions | |||
Function pointer conversion | Qualification Adjustment | ||
Integral promotions | |||
Floating-point promotion | Promotion | Promotion | |
Integral conversions | |||
Floating-point conversions | |||
Floating-integral conversions | |||
Pointer conversions | Conversion | Conversion | |
Pointer to member conversions | |||
Boolean conversions |
struct A {};
struct B : public A {} b;
int f(A&);
int f(B&);
int i = f(b); // calls f(B&), an exact match, rather than f(A&), a conversion
void f(std::initializer_list<int>); f( {} ); // OK: f(initializer_list<int>) identity conversion f( {1,2,3} ); // OK: f(initializer_list<int>) identity conversion f( {'a','b'} ); // OK: f(initializer_list<int>) integral promotion f( {1.0} ); // error: narrowing struct A { A(std::initializer_list<double>); // #1 A(std::initializer_list<complex<double>>); // #2 A(std::initializer_list<std::string>); // #3 }; A a{ 1.0,2.0 }; // OK, uses #1 void g(A); g({ "foo", "bar" }); // OK, uses #3 typedef int IA[3]; void h(const IA&); h({ 1, 2, 3 }); // OK: identity conversion
struct A { A(std::initializer_list<int>); }; void f(A); f( {'a', 'b'} ); // OK: f(A(std::initializer_list<int>)) user-defined conversion struct B { B(int, double); }; void g(B); g( {'a', 'b'} ); // OK: g(B(int, double)) user-defined conversion g( {1.0, 1.0} ); // error: narrowing void f(B); f( {'a', 'b'} ); // error: ambiguous f(A) or f(B) struct C { C(std::string); }; void h(C); h({"foo"}); // OK: h(C(std::string("foo"))) struct D { D(A, C); }; void i(D); i({ {1,2}, {"bar"} }); // OK: i(D(A(std::initializer_list<int>{1,2}), C(std::string("bar"))))
struct A { int m1; double m2; }; void f(A); f( {'a', 'b'} ); // OK: f(A(int,double)) user-defined conversion f( {1.0} ); // error: narrowing
struct A { int m1; double m2; }; void f(const A&); f( {'a', 'b'} ); // OK: f(A(int,double)) user-defined conversion f( {1.0} ); // error: narrowing void g(const double &); g({1}); // same conversion as int to double
void f(int); f( {'a'} ); // OK: same conversion as char to int f( {1.0} ); // error: narrowing