[class.conv] (original) (raw)

11 Classes [class]

11.4 Class members [class.mem]

11.4.8 Conversions [class.conv]

11.4.8.1 General [class.conv.general]

Type conversions of class objects can be specified by constructors and by conversion functions.

[Note 1:

See [over.match] for a discussion of the use of conversions in function calls as well as examples below.

— _end note_]

At most one user-defined conversion (constructor or conversion function) is implicitly applied to a single value.

[Example 1: struct X { operator int();};struct Y { operator X();}; Y a;int b = a; int c = X(a); — _end example_]

User-defined conversions are used implicitly only if they are unambiguous.

A conversion function in a derived class does not hide a conversion function in a base class unless the two functions convert to the same type.

Function overload resolution ([over.match.best]) selects the best conversion function to perform the conversion.

[Example 2: struct X { operator int();};struct Y : X { operator char();};void f(Y& a) { if (a) { } } — _end example_]

11.4.8.2 Conversion by constructor [class.conv.ctor]

A constructor that is not explicit ([dcl.fct.spec]) specifies a conversion from the types of its parameters (if any) to the type of its class.

Such a constructor is called aconverting constructor.

[Example 1: struct X { X(int); X(const char*, int =0); X(int, int);};void f(X arg) { X a = 1; X b = "Jessie"; a = 2; f(3); f({1, 2}); } — _end example_]

[Note 1:

An explicit constructor constructs objects just like non-explicit constructors, but does so only where the direct-initialization syntax ([dcl.init]) or where casts ([expr.static.cast], [expr.cast]) are explicitly used; see also [over.match.copy].

A default constructor can be an explicit constructor; such a constructor will be used to perform default-initialization or value-initialization ([dcl.init]).

[Example 2: struct Z { explicit Z();explicit Z(int);explicit Z(int, int);}; Z a; Z b{}; Z c = {}; Z a1 = 1; Z a3 = Z(1); Z a2(1); Z* p = new Z(1); Z a4 = (Z)1; Z a5 = static_cast<Z>(1); Z a6 = { 3, 4 }; — _end example_]

— _end note_]

A non-explicit copy/move constructor ([class.copy.ctor]) is a converting constructor.

[Note 2:

An implicitly-declared copy/move constructor is not an explicit constructor; it can be called for implicit type conversions.

— _end note_]

11.4.8.3 Conversion functions [class.conv.fct]

A member function of a class X having no parameters with a name of the form

conversion-function-id:
operator conversion-type-id

specifies a conversion fromXto the type specified by theconversion-type-id.

Such functions are called conversion functions.

The type of the conversion function ([dcl.fct]) is “function taking no parameter returningconversion-type-id.

A conversion function is never used to convert a (possibly cv-qualified) object to the (possibly cv-qualified) same object type (or a reference to it), to a (possibly cv-qualified) base class of that type (or a reference to it), or to cv void.110

[Example 1: struct X { operator int();operator auto() -> short; };void f(X a) { int i = int(a); i = (int)a; i = a;}

In all three cases the value assigned will be converted byX​::​operator int().

— _end example_]

A conversion function may be explicit ([dcl.fct.spec]), in which case it is only considered as a user-defined conversion for direct-initialization ([dcl.init]).

Otherwise, user-defined conversions are not restricted to use in assignments and initializations.

[Example 2: class Y { };struct Z { explicit operator Y() const;};void h(Z z) { Y y1(z); Y y2 = z; Y y3 = (Y)z; } void g(X a, X b) { int i = (a) ? 1+a : 0;int j = (a&&b) ? a+b : i;if (a) { } } — _end example_]

Theconversion-type-idshall not represent a function type nor an array type.

Theconversion-type-idin aconversion-function-idis the longest sequence of tokens that could possibly form a conversion-type-id.

[Note 1:

This prevents ambiguities between the declarator operator * and its expression counterparts.

[Example 3: &ac.operator int*i;

The * is the pointer declarator and not the multiplication operator.

— _end example_]

This rule also prevents ambiguities for attributes.

[Example 4: operator int [[noreturn]] (); — _end example_]

— _end note_]

Conversion functions are inherited.

Conversion functions can be virtual.

A conversion function template shall not have a deduced return type ([dcl.spec.auto]).

[Example 5: struct S { operator auto() const { return 10; } template<class T> operator auto() const { return 1.2; } }; — _end example_]