Implicit conversions
Implicit conversions are performed whenever an expression of some type T1
is used in context that does not accept that type, but accepts some other type T2
; in particular:
 when the expression is used as the argument when calling a function that is declared with
T2
as parameter;  when the expression is used as an operand with an operator that expects
T2
;  when initializing a new object of type
T2
, includingreturn
statement in a function returningT2
;  when the expression is used in a switch statement (
T2
is integral type);  when the expression is used in an if statement or a loop (
T2
is bool).
The program is wellformed (compiles) only if there exists one unambiguous implicit conversion sequence from T1
to T2
.
If there are multiple overloads of the function or operator being called, after the implicit conversion sequence is built from T1
to each available T2
, overload resolution rules decide which overload is compiled.
Note: in arithmetic expressions, the destination type for the implicit conversions on the operands to binary operators is determined by a separate set of rules: usual arithmetic conversions.
Contents 
[edit] Order of the conversions
Implicit conversion sequence consists of the following, in this order:
When considering the argument to a constructor or to a userdefined conversion function, only one standard conversion sequence is allowed (otherwise userdefined conversions could be effectively chained). When converting from one nonclass type to another nonclass type, only a standard conversion sequence is allowed.
A standard conversion sequence consists of the following, in this order:
 lvaluetorvalue conversion,
 arraytopointer conversion, and
 functiontopointer conversion;
3) zero or one function pointer conversion;

(since C++17) 
A userdefined conversion consists of zero or one nonexplicit singleargument converting constructor or nonexplicit conversion function call.
An expression e is said to be implicitly convertible to T2
if and only if T2
can be copyinitialized from e, that is the declaration T2 t = e; is wellformed (can be compiled), for some invented temporary t
. Note that this is different from direct initialization (T2 t(e)), where explicit constructors and conversion functions would additionally be considered.
[edit] Contextual conversions
In the following contexts, the type bool is expected and the implicit conversion is performed if the declaration bool t(e); is wellformed (that is, an explicit conversion function such as explicit T::operator bool() const; is considered). Such expression e is said to be contextually converted to bool.

(since C++11) 
In the following contexts, a contextspecific type T
is expected, and the expression e of class type E
is only allowed if

(until C++14) 

(since C++14) 
Such expression e is said to be contextually implicitly converted to the specified type T
. Note that explicit conversion functions are not considered, even though they are considered in contextual conversions to bool.(since C++11)
 the argument of the deleteexpression (
T
is any object pointer type);  integral constant expression, where a literal class is used (
T
is any integral or unscoped enumeration type, the selected userdefined conversion function must be constexpr);  the controlling expression of the
switch
statement (T
is any integral or enumeration type).
#include <cassert> template<typename T> class zero_init { T val; public: zero_init() : val(static_cast<T>(0)) {} zero_init(T val) : val(val) {} operator T&() { return val; } operator T() const { return val; } }; int main() { zero_init<int> i; assert(i == 0); i = 7; assert(i == 7); switch (i) {} // error until C++14 (more than one conversion function) // OK since C++14 (both functions convert to the same type int) switch (i + 0) {} // always okay (implicit conversion) }
[edit] Value transformations
Value transformations are conversions that change the value category of an expression. They take place whenever an expression appears as an operand of an operator that expects an expression of a different value category:
 Whenever a glvalue appears as an operand of an operator that requires a prvalue for that operand, the lvaluetorvalue, arraytopointer, or functiontopointer standard conversions are applied to convert the expression to a prvalue.

(since C++17) 
[edit] Lvaluetorvalue conversion
An lvalue(until C++11)A glvalue(since C++11) of any nonfunction, nonarray type T
can be implicitly converted to an rvalue(until C++11)a prvalue(since C++11):
 If
T
is not a class type, the type of the rvalue(until C++11)prvalue(since C++11) is the cvunqualified version ofT
.  Otherwise, the type of the rvalue(until C++11)prvalue(since C++11) is
T
.
If an lvaluetorvalue conversion from an incomplete type is required by a program, that program is illformed.
When an lvaluetorvalue conversion occurs within the operand of 
(until C++11) 
When an lvaluetorvalue conversion is applied to an expression E, the value contained in the referenced object is not accessed if:

(since C++11) 
The result of the conversion is the value contained in the object indicated by the lvalue. 
(until C++11)  
The result of the conversion is determined according to the following rules:

(since C++11) 
This conversion models the act of reading a value from a memory location into a CPU register.
[edit] Arraytopointer conversion
An lvalue or rvalue of type “array of N
T
” or “array of unknown bound of T
” can be implicitly converted to a prvalue of type “pointer to T
”. If the array is a prvalue, temporary materialization occurs.(since C++17) The resulting pointer refers to the first element of the array (see Arraytopointer decay for details).
[edit] Functiontopointer conversion
An lvalue of function type can be implicitly converted to a prvalue pointer to that function. This does not apply to nonstatic member functions because lvalues that refer to nonstatic member functions do not exist.
Temporary materializationA prvalue of any complete type If struct S { int m; }; int i = S().m; // member access expects glvalue as of C++17; // S() prvalue is converted to xvalue Temporary materialization occurs in the following situations:
Note that temporary materialization does not occur when initializing an object from a prvalue of the same type (by directinitialization or copyinitialization): such object is initialized directly from the initializer. This ensures “guaranteed copy elision”. 
(since C++17) 
[edit] Integral promotion
prvalues of small integral types (such as char) and unscoped enumeration types may be converted to prvalues of larger integral types (such as int). In particular, arithmetic operators do not accept types smaller than int as arguments, and integral promotions are automatically applied after lvaluetorvalue conversion, if applicable. This conversion always preserves the value.
The following implicit conversions in this section are classified as integral promotions.
[edit] Promotion from integral types
A prvalue of type bool can be converted to a prvalue of type int, with false becoming 0 and true becoming 1.
For a prvalue val of an integral type T
except bool:
 val can be converted to a prvalue of type int if int can represent all the values of the bitfield;
 otherwise, val can be converted to unsigned int if unsigned int can represent all the values of the bitfield;
 otherwise, val can be converted according to the rules specified in item (3).
 if
T
is char8_t, (since C++20)char16_t, char32_t or (since C++11)wchar_t, val can be converted according to the rules specified in item (3);  otherwise, if the integer conversion rank of
T
is lower than the rank of int:
 val can be converted to a prvalue of type int if int can represent all the values of
T
;  otherwise, val can be converted to a prvalue of type unsigned int.
 val can be converted to a prvalue of type int if int can represent all the values of
T
is one of the given character types), val can be converted to a prvalue of the first of the following types that can represent all the values of its underlying type:
 int
 unsigned int
 long
 unsigned long

(since C++11) 
[edit] Promotion from enumeration types
A prvalue of an unscoped enumeration type whose underlying type is not fixed can be converted to a prvalue of the first type from the following list able to hold their entire value range:
 int
 unsigned int
 long
 unsigned long

(since C++11) 
A prvalue of an unscoped enumeration type whose underlying type is fixed can be converted to its underlying type. Moreover, if the underlying type is also subject to integral promotion, to the promoted underlying type. Conversion to the unpromoted underlying type is better for the purposes of overload resolution. 
(since C++11) 
Note that all other conversions are not promotions; for example, overload resolution chooses char > int (promotion) over char > short (conversion).
[edit] Floatingpoint promotion
A prvalue of type float can be converted to a prvalue of type double. The value does not change.
This conversion is called floatingpoint promotion.
[edit] Numeric conversions
Unlike the promotions, numeric conversions may change the values, with potential loss of precision.
[edit] Integral conversions
A prvalue of an integer type or of an unscoped enumeration type can be converted to any other integer type. If the conversion is listed under integral promotions, it is a promotion and not a conversion.
 If the destination type is unsigned, the resulting value is the smallest unsigned value equal to the source value modulo 2n
where n is the number of bits used to represent the destination type.
 That is, depending on whether the destination type is wider or narrower, signed integers are signextended^{[1]} or truncated and unsigned integers are zeroextended or truncated respectively.
 If the destination type is signed, the value does not change if the source integer can be represented in the destination type. Otherwise the result is implementationdefined(until C++20)the unique value of the destination type equal to the source value modulo 2n
where n is the number of bits used to represent the destination type(since C++20) (note that this is different from signed integer arithmetic overflow, which is undefined).  If the source type is bool, the value false is converted to zero and the value true is converted to the value one of the destination type (note that if the destination type is int, this is an integer promotion, not an integer conversion).
 If the destination type is bool, this is a boolean conversion (see below).
 ↑ This only applies if the arithmetic is two's complement which is only required for the exactwidth integer types. Note, however, that at the moment all platforms with a C++ compiler use two's complement arithmetic.
[edit] Floatingpoint conversions
A prvalue of a floatingpoint type can be converted to a prvalue of any other floatingpoint type. 
(until C++23) 
A prvalue of a floatingpoint type can be converted to a prvalue of any other floatingpoint type with a greater or equal floatingpoint conversion rank. A prvalue of a standard floatingpoint type can be converted to a prvalue of any other standard floatingpoint type.

(since C++23) 
If the conversion is listed under floatingpoint promotions, it is a promotion and not a conversion.
 If the source value can be represented exactly in the destination type, it does not change.
 If the source value is between two representable values of the destination type, the result is one of those two values (it is implementationdefined which one, although if IEEE arithmetic is supported, rounding defaults to nearest).
 Otherwise, the behavior is undefined.
[edit] Floating–integral conversions
A prvalue of floatingpoint type can be converted to a prvalue of any integer type. The fractional part is truncated, that is, the fractional part is discarded.
 If the truncated value cannot fit into the destination type, the behavior is undefined (even when the destination type is unsigned, modulo arithmetic does not apply).
 If the destination type is bool, this is a boolean conversion (see below).
A prvalue of integer or unscoped enumeration type can be converted to a prvalue of any floatingpoint type. The result is exact if possible.
 If the value can fit into the destination type but cannot be represented exactly, it is implementation defined whether the closest higher or the closest lower representable value will be selected, although if IEEE arithmetic is supported, rounding defaults to nearest.
 If the value cannot fit into the destination type, the behavior is undefined.
 If the source type is bool, the value false is converted to zero, and the value true is converted to one.
[edit] Pointer conversions
A null pointer constant can be converted to any pointer type, and the result is the null pointer value of that type. Such conversion (known as null pointer conversion) is allowed to convert to a cvqualified type as a single conversion, that is, it is not considered a combination of numeric and qualifying conversions.
A prvalue pointer to any (optionally cvqualified) object type T
can be converted to a prvalue pointer to (identically cvqualified) void. The resulting pointer represents the same location in memory as the original pointer value.
 If the original pointer is a null pointer value, the result is a null pointer value of the destination type.
A prvalue ptr of type “pointer to (possibly cvqualified) Derived
” can be converted to a prvalue of type “pointer to (possibly cvqualified) Base
”, where Base
is a base class of Derived
, and Derived
is a complete class type. If the Base
is inaccessible or ambiguous, the program is illformed.
 If ptr is a null pointer value, the result is also a null pointer value.
 Otherwise, if
Base
is a virtual base class ofDerived
and ptr does not point to an object whose type is similar toDerived
and that is within its lifetime or within its period of construction or destruction, the behavior is undefined.  Otherwise, the result is a pointer to the base class subobject of the derived class object.
[edit] Pointertomember conversions
A null pointer constant can be converted to any pointertomember type, and the result is the null member pointer value of that type. Such conversion (known as null member pointer conversion) is allowed to convert to a cvqualified type as a single conversion, that is, it is not considered a combination of numeric and qualifying conversions.
A prvalue of type “pointer to member of Base
of type (possibly cvqualified) T
” can be converted to a prvalue of type “pointer to member of Derived
of type (identically cvqualified) T
”, where Base
is a base class of Derived
, and Derived
is a complete class type. If Base
is inaccessible, ambiguous, or virtual base of Derived
or is a base of some intermediate virtual base of Derived
, the program is illformed.
 If
Derived
does not contain the original member and is not a base class of the class containing the original member, the behavior is undefined.  Otherwise, the resulting pointer can be dereferenced with a
Derived
object, and it will access the member within theBase
base subobject of thatDerived
object.
[edit] Boolean conversions
A prvalue of integral, floatingpoint, unscoped enumeration, pointer, and pointertomember types can be converted to a prvalue of type bool.
The value zero (for integral, floatingpoint, and unscoped enumeration) and the null pointer and the null pointertomember values become false. All other values become true.
In the context of a directinitialization, a bool object may be initialized from a prvalue of type std::nullptr_t, including nullptr. The resulting value is false. However, this is not considered to be an implicit conversion. 
(since C++11) 
[edit] Qualification conversions
Generally speaking:
 A prvalue of type pointer to cvqualified type
T
can be converted to a prvalue pointer to a more cvqualified same typeT
(in other words, constness and volatility can be added).  A prvalue of type pointer to member of cvqualified type
T
in classX
can be converted to a prvalue pointer to member of more cvqualified typeT
in classX
.
The formal definition of “qualification conversion” is given below.
[edit] Similar types
Informally, two types are similar if, ignoring toplevel cvqualification:
 they are the same type; or
 they are both pointers, and the pointedto types are similar; or
 they are both pointers to member of the same class, and the types of the pointedto members are similar; or
 they are both arrays and the array element types are similar.
For example:
 const int* const * and int** are similar;
 int (*)(int*) and int (*)(const int*) are not similar;
 const int (*)(int*) and int (*)(int*) are not similar;
 int (*)(int* const) and int (*)(int*) are similar (they are the same type);
 std::pair<int, int> and std::pair<const int, int> are not similar.
Formally, type similarity is defined in terms of qualificationdecomposition.
A qualificationdecomposition of a type T
is a sequence of components cv_i
and P_i
such that T
is “cv_0 P_0 cv_1 P_1 ... cv_n−1 P_n−1 cv_n U
” for nonnegative n, where
 each
cv_i
is a set of const and volatile, and  each
P_i
is
 “pointer to”,
 “pointer to member of class
C_i
of type”,  “array of N_i”, or
 “array of unknown bound of”.
If P_i
designates an array, the cvqualifiers cv_i+1
on the element type are also taken as the cvqualifiers cv_i
of the array.
// T is “pointer to pointer to const int”, it has 3 qualificationdecompositions: // n = 0 > cv_0 is empty, U is “pointer to pointer to const int” // n = 1 > cv_0 is empty, P_0 is “pointer to”, // cv_1 is empty, U is “pointer to const int” // n = 2 > cv_0 is empty, P_0 is “pointer to”, // cv_1 is empty, P_1 is “pointer to”, // cv_2 is “const", U is “int” using T = const int**; // substitute any of the following type to U gives one of the decompositions: // U = U0 > the decomposition with n = 0: U0 // U = U1 > the decomposition with n = 1: pointer to [U1] // U = U2 > the decomposition with n = 2: pointer to [pointer to [const U2]] using U2 = int; using U1 = const U2*; using U0 = U1*;
Two types T1
and T2
are similar if there exists a qualificationdecomposition for each of them, where all following conditions are satisfied for the two qualificationdecompositions:
 They have the same n.
 The types denoted by
U
are the same.  The corresponding
P_i
components are the same or one is “array of N_i” and the other is “array of unknown bound of”(since C++20) for all i.
// the qualificationdecomposition with n = 2: // pointer to [volatile pointer to [const int]] using T1 = const int* volatile *; // the qualificationdecomposition with n = 2: // const pointer to [pointer to [int]] using T2 = int** const; // For the two qualificationdecompositions above // although cv_0, cv_1 and cv_2 are all different, // they have the same n, U, P_0 and P_1, // therefore types T1 and T2 are similar.
[edit] Combining cvqualifications
In the description below, the longest qualificationdecomposition of type Tn
is denoted as Dn
, and its components are denoted as cvn_i
and Pn_i
.
A prvalue expression of type
The qualificationcombined type of two types

(until C++20) 
The qualificationcombined type of two types
A prvalue of type 
(since C++20) 
// longest qualificationdecomposition of T1 (n = 2): // pointer to [pointer to [char]] using T1 = char**; // longest qualificationdecomposition of T2 (n = 2): // pointer to [pointer to [const char]] using T2 = const char**; // Determining the cv3_i and T_i components of D3 (n = 2): // cv3_1 = empty (union of empty cv1_1 and empty cv2_1) // cv3_2 = “const” (union of empty cv1_2 and “const” cv2_2) // P3_0 = “pointer to” (no array of unknown bound, use P1_0) // P3_1 = “pointer to” (no array of unknown bound, use P1_1) // All components except cv_2 are the same, cv3_2 is different from cv1_2, // therefore add “const” to cv3_k for each k in [1, 2): cv3_1 becomes “const”. // T3 is “pointer to const pointer to const char”, i.e., const char* const *. using T3 = /* the qualificationcombined type of T1 and T2 */; int main() { const char c = 'c'; char* pc; T1 ppc = &pc; T2 pcc = ppc; // Error: T3 is not the same as cvunqualified T2, // no implicit conversion. *pcc = &c; *pc = 'C'; // If the erroneous assignment above is allowed, // the const object “c” may be modified. }
Note that in the C programming language, const/volatile can be added to the first level only:
char** p = 0; char * const* p1 = p; // OK in C and C++ const char* const * p2 = p; // error in C, OK in C++
Function pointer conversions
void (*p)(); void (**pp)() noexcept = &p; // error: cannot convert to pointer to noexcept function struct S { typedef void (*p)(); operator p(); }; void (*q)() noexcept = S(); // error: cannot convert to pointer to noexcept function 
(since C++17) 
[edit] The safe bool problem
Until C++11, designing a class that should be usable in boolean contexts (e.g. if (obj) { ... }) presented a problem: given a userdefined conversion function, such as T::operator bool() const;, the implicit conversion sequence allowed one additional standard conversion sequence after that function call, which means the resultant bool could be converted to int, allowing such code as obj << 1; or int i = obj;.
One early solution for this can be seen in std::basic_ios, which initially defines operator void*, so that the code such as if (std::cin) {...} compiles because void* is convertible to bool, but int n = std::cout; does not compile because void* is not convertible to int. This still allows nonsense code such as delete std::cout; to compile.
Many preC++11 third party libraries were designed with a more elaborate solution, known as the Safe Bool idiom. std::basic_ios also allowed this idiom via LWG issue 468, and operator void* was replaced (see notes).
Since C++11, explicit bool conversion can also be used to resolve the safe bool problem.
[edit] Defect reports
The following behaviorchanging defect reports were applied retroactively to previously published C++ standards.
DR  Applied to  Behavior as published  Correct behavior 

CWG 170  C++98  the behavior of pointertomember conversions was unclear if the derived class does not have the original member 
made clear 
CWG 172  C++98  enumeration type was promoted based on its underlying type  based on its value range instead 
CWG 330 (N4261) 
C++98  the conversion from double* const (*p)[3] to double const * const (*p)[3] was invalid 
made valid 
CWG 519  C++98  null pointer values were not guaranteed to be preserved when converting to another pointer type 
always preserved 
CWG 616  C++98  the behavior of lvalue to rvalue conversion of any uninitialized object and pointer objects of invalid values was always undefined 
indeterminate unsigned char is allowed; use of invalid pointers is implementationdefined 
CWG 685  C++98  the underlying type of an enumeration type was not prioritized in integral promotion if it is fixed 
prioritized 
CWG 707  C++98  integer to floating point conversion had defined behavior in all cases 
the behavior is undefined if the value being converted is out of the destination range 
CWG 1423  C++11  std::nullptr_t was convertible to bool in both direct and copyinitialization 
directinitialization only 
CWG 1773  C++11  a name expression that appears in a potentiallyevaluated expression such that the object named is not odrused might still be evaluated during an lvaluetorvalue conversion 
not evaluated 
CWG 1781  C++11  std::nullptr_t to bool was considered an implicit conversion even though it is only valid for directinitialization 
no longer considered an implicit conversion 
CWG 1787  C++98  the behavior of reading from an indeterminate unsigned char cached in a register was undefined 
made welldefined 
CWG 1981  C++11  contextual conversions considered explicit conversion functions  not considered 
CWG 2140  C++11  it was unclear whether lvaluetorvalue conversions from std::nullptr_t lvalues fetch these lvalues from memory 
not fetched 
CWG 2310  C++98  for derivedtobase pointer conversions and basetoderived pointertomember conversions, the derived class type could be incomplete 
must be complete 
CWG 2484  C++20  char8_t and char16_t had different integral promotion strategies, but they can fit both of them 
char8_t should be promoted in the same way as char16_t 
CWG 2485  C++98  integral promotions involving bitfields were not specified well  improved the specification 
CWG 2813  C++23  temporary materialization would occur when an explicit object member function of a class prvalue is invoked 
will not occur in this case 
CWG 2861  C++98  a pointer to a typeinaccessible object could be converted a pointer to a base class subobject 
the behavior is undefined in this case 
[edit] See also
C documentation for Implicit conversions
