15 Special member functions [special]

15.3 Conversions [class.conv]

Type conversions of class objects can be specified by constructors and by conversion functions.
These conversions are called user-defined conversions and are used for implicit type conversions (Clause [conv]), for initialization, and for explicit type conversions ([expr.cast], [expr.static.cast]).
User-defined conversions are applied only where they are unambiguous ([class.member.lookup], [class.conv.fct]).
Conversions obey the access control rules.
Access control is applied after ambiguity resolution ([basic.lookup]).
[Note
:
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
:
struct X {
  operator int();
};

struct Y {
  operator X();
};

Y a;
int b = a;          // error, a.operator X().operator int() not tried
int c = X(a);       // OK: a.operator X().operator int()
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 selects the best conversion function to perform the conversion.
[Example
:
struct X {
  operator int();
};

struct Y : X {
    operator char();
};

void f(Y& a) {
  if (a) {          // ill-formed: X​::​operator int() or Y​::​operator char()
  }
}
end example
]

15.3.1 Conversion by constructor [class.conv.ctor]

A constructor declared without the function-specifier explicit specifies a conversion from the types of its parameters (if any) to the type of its class.
Such a constructor is called a converting constructor.
[Example
:
struct X {
    X(int);
    X(const char*, int =0);
    X(int, int);
};

void f(X arg) {
  X a = 1;          // a = X(1)
  X b = "Jessie";   // b = X("Jessie",0)
  a = 2;            // a = X(2)
  f(3);             // f(X(3))
  f({1, 2});        // f(X(1,2))
}
end example
]
[Note
:
An explicit constructor constructs objects just like non-explicit constructors, but does so only where the direct-initialization syntax or where casts ([expr.static.cast], [expr.cast]) are explicitly used; see also [over.match.copy].
A default constructor may be an explicit constructor; such a constructor will be used to perform default-initialization or value-initialization.
[Example
:
struct Z {
  explicit Z();
  explicit Z(int);
  explicit Z(int, int);
};

Z a;                            // OK: default-initialization performed
Z b{};                          // OK: direct initialization syntax used
Z c = {};                       // error: copy-list-initialization
Z a1 = 1;                       // error: no implicit conversion
Z a3 = Z(1);                    // OK: direct initialization syntax used
Z a2(1);                        // OK: direct initialization syntax used
Z* p = new Z(1);                // OK: direct initialization syntax used
Z a4 = (Z)1;                    // OK: explicit cast used
Z a5 = static_cast<Z>(1);       // OK: explicit cast used
Z a6 = { 3, 4 };                // error: no implicit conversion
end example
]
end note
]
A non-explicit copy/move constructor ([class.copy]) is a converting constructor.
[Note
:
An implicitly-declared copy/move constructor is not an explicit constructor; it may be called for implicit type conversions.
end note
]

15.3.2 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
conversion-type-id:
	type-specifier-seq conversion-declarator
conversion-declarator:
	ptr-operator conversion-declarator
specifies a conversion from X to the type specified by the conversion-type-id.
Such functions are called conversion functions.
A decl-specifier in the decl-specifier-seq of a conversion function (if any) shall be neither a defining-type-specifier nor static.
The type of the conversion function ([dcl.fct]) is “function taking no parameter 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 (possibly cv-qualified) void.117
[Example
:
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, in which case it is only considered as a user-defined conversion for direct-initialization.
Otherwise, user-defined conversions are not restricted to use in assignments and initializations.
[Example
:
class Y { };
struct Z {
  explicit operator Y() const;
};

void h(Z z) {
  Y y1(z);          // OK: direct-initialization
  Y y2 = z;         // ill-formed: 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
:
This prevents ambiguities between the declarator operator * and its expression counterparts.
[Example
:
&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
:
operator int [[noreturn]] ();   // error: noreturn attribute applied to a type
end example
]
end note
]
Conversion functions are inherited.
Conversion functions can be virtual.
A conversion function template shall not have a deduced return type.
[Example
:
struct S {
  operator auto() const { return 10; }      // OK
  template<class T>
  operator auto() const { return 1.2; }     // error: conversion function template
};
end example
]
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.
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.