11 Classes [class]

11.4 Class members [class.mem]

11.4.8 Conversions [class.conv]

11.4.8.3 Conversion functions [class.conv.fct]

A declaration whose declarator-id has an unqualified-id that is a conversion-function-id declares a conversion function; its declarator shall be a function declarator ([dcl.fct]) of the form where the ptr-declarator consists solely of an id-expression, an optional attribute-specifier-seq, and optional surrounding parentheses, and the id-expression has one of the following forms:
A conversion function shall have no non-object parameters and shall be a non-static member function of a class or class template X; it specifies a conversion from X to the type specified by the conversion-type-id, interpreted as a type-id ([dcl.name]).
A decl-specifier in the decl-specifier-seq of a conversion function (if any) shall not be a defining-type-specifier.
The type of the conversion function is “noexcept function taking no parameter cv-qualifier-seq ref-qualifier returning conversion-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.97
[Example 1: struct X { operator int(); operator auto() -> short; // error: trailing return type }; void f(X a) { int i = int(a); i = (int)a; i = a; }
In all three cases the value assigned will be converted by X​::​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); // OK, direct-initialization Y y2 = z; // error: no conversion function candidate for copy-initialization Y y3 = (Y)z; // OK, cast notation } void g(X a, X b) { int i = (a) ? 1+a : 0; int j = (a&&b) ? a+b : i; if (a) { } } — end example]
The conversion-type-id shall not represent a function type nor an array type.
The conversion-type-id in a conversion-function-id is 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; // syntax error: // parsed as: &(ac.operator int *)i // not as: &(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]] (); // error: noreturn attribute applied to a type — end example]
— end note]
[Note 2: 
A conversion function in a derived class hides only conversion functions in base classes that convert to the same type.
A conversion function template with a dependent return type hides only templates in base classes that correspond to it ([class.member.lookup]); otherwise, it hides and is hidden as a non-template function.
Function overload resolution ([over.match.best]) selects the best conversion function to perform the conversion.
[Example 5: struct X { operator int(); }; struct Y : X { operator char(); }; void f(Y& a) { if (a) { // error: ambiguous between X​::​operator int() and Y​::​operator char() } } — end example]
— end note]
Conversion functions can be virtual.
A conversion function template shall not have a deduced return type ([dcl.spec.auto]).
[Example 6: struct S { operator auto() const { return 10; } // OK template<class T> operator auto() const { return 1.2; } // error: conversion function template }; — end example]
97)97)
These conversions are considered as standard conversions for the purposes of overload resolution ([over.best.ics], [over.ics.ref]) and therefore initialization ([dcl.init]) and explicit casts ([expr.static.cast]).
A conversion to void does not invoke any conversion function ([expr.static.cast]).
Even though never directly called to perform a conversion, such conversion functions can be declared and can potentially be reached through a call to a virtual conversion function in a base class.