cpp/language/implicit conversion: Difference between revisions
From cppreference.com
All enumeration types in C++98/03 are unscoped. No rev-box needed. |
Added CWG issue #2901 DR (part 1/3). |
||
| (33 intermediate revisions by 11 users not shown) | |||
| Line 6: | Line 6: | ||
* when the expression is used as an operand with an operator that expects {{tt|T2}}; | * when the expression is used as an operand with an operator that expects {{tt|T2}}; | ||
* when initializing a new object of type {{tt|T2}}, including {{tt|return}} statement in a function returning {{tt|T2}}; | * when initializing a new object of type {{tt|T2}}, including {{tt|return}} statement in a function returning {{tt|T2}}; | ||
* when the expression is used in a {{ | * when the expression is used in a {{|switch}} statement ({{tt|T2}} is integral type); | ||
* when the expression is used in an {{ | * when the expression is used in an {{|if}} statement or a loop ({{tt|T2}} is {{c/core|bool}}). | ||
The program is well-formed (compiles) only if there exists one unambiguous ''implicit conversion sequence'' from {{tt|T1}} to {{tt|T2}}. | The program is well-formed (compiles) only if there exists one unambiguous ''implicit conversion sequence'' from {{tt|T1}} to {{tt|T2}}. | ||
If there are multiple overloads of the function or operator being called, after the implicit conversion sequence is built from {{tt|T1}} to each available {{tt|T2}}, {{rlp|overload resolution}} rules decide which overload is compiled. | If there are multiple overloads of the function or operator being called, after the implicit conversion sequence is built from {{tt|T1}} to each available {{tt|T2}}, {{rlp|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 | 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{{rlp|usual arithmetic conversions}}. | ||
===Order of the conversions=== | ===Order of the conversions=== | ||
| Line 20: | Line 20: | ||
@3@ zero or one ''standard conversion sequence'' (only if a user-defined conversion is used). | @3@ zero or one ''standard conversion sequence'' (only if a user-defined conversion is used). | ||
When considering the argument to a constructor or to a user-defined conversion function, only | When considering the argument to a constructor or to a user-defined conversion function, only standard conversion sequence is allowed (otherwise user-defined conversions could be effectively chained). When converting from one non-class type to another non-class type, only a standard conversion sequence is allowed. | ||
A standard conversion sequence consists of the following, in this order: | A standard conversion sequence consists of the following, in this order: | ||
@1@ zero or one conversion from the following set: ''lvalue-to-rvalue conversion'', ''array-to-pointer conversion'', and ''function-to-pointer conversion''; | @1@ zero or one conversion from the following set: | ||
''lvalue-to-rvalue conversion'', | |||
''array-to-pointer conversion'', and | |||
''function-to-pointer conversion''; | |||
@2@ zero or one ''numeric promotion'' or ''numeric conversion''; | @2@ zero or one ''numeric promotion'' or ''numeric conversion''; | ||
| Line 38: | Line 41: | ||
{{rrev|since=c++11| | {{rrev|since=c++11| | ||
In the following contexts, the type {{c/core|bool}} is expected and the implicit conversion is performed if the declaration {{c|1=bool t(e);}} is well-formed (that is, an explicit conversion function such as {{c|explicit T::operator bool() const;}} is considered). Such expression {{c|e}} is said to be ''contextually converted to {{c/core|bool}}''. | In the following contexts, the type {{c/core|bool}} is expected and the implicit conversion is performed if the declaration {{c|1=bool t(e);}} is well-formed (that is, an explicit conversion function such as {{c|explicit T::operator bool() const;}} is considered). Such expression {{c|e}} is said to be ''contextually converted to {{c/core|bool}}''. | ||
* the controlling expression of {{c/core|if}}, {{c/core|while}}, {{c/core|for}}; | |||
* the operands of the built-in logical operators {{tt|!}}, {{tt|&&}} and {{tt|{{!!}}}}; | |||
* the first operand of the conditional operator {{tt|?:}}; | |||
* the predicate in a {{rlpt|static_assert}} declaration; | |||
* the expression in a {{rlpt|noexcept spec|noexcept}} specifier; | |||
{{rrev|since=c++20| | {{rrev|since=c++20| | ||
* the expression in an {{rlpt|explicit}} specifier; | |||
}} | }} | ||
}} | }} | ||
| Line 58: | Line 61: | ||
Such expression {{c|e}} is said to be ''contextually implicitly converted'' to the specified type {{tt|T}}. {{rev inl|since=c++11|Note that explicit conversion functions are not considered, even though they are considered in contextual conversions to {{c/core|bool}}.}} | Such expression {{c|e}} is said to be ''contextually implicitly converted'' to the specified type {{tt|T}}. {{rev inl|since=c++11|Note that explicit conversion functions are not considered, even though they are considered in contextual conversions to {{c/core|bool}}.}} | ||
* the argument of the {{rlp|delete|delete-expression}} ({{tt|T}} is any object pointer type); | * the argument of the {{rlp|delete|delete-expression}} ({{tt|T}} is any object pointer type); | ||
* {{ | * {{|constant expression#Integral constant expression}}, where a literal class is used ({{tt|T}} is any integral or unscoped enumeration type, the selected user-defined conversion function must be {{rlp|constexpr}}); | ||
* the controlling expression of the {{rlpt|switch}} statement ({{tt|T}} is any integral or enumeration type). | * the controlling expression of the {{rlpt|switch}} statement ({{tt|T}} is any integral or enumeration type). | ||
| Line 90: | Line 93: | ||
===Value transformations=== | ===Value transformations=== | ||
Value transformations are conversions that change the {{rlp|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. | Value transformations are conversions that change the {{rlp|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 | ||
. | |||
====Lvalue-to-rvalue conversion==== | ====Lvalue-to-rvalue conversion==== | ||
{{rev inl|until=c++11|An {{|value category#lvalue}}}}{{rev inl|since=c++11|A {{|value category#glvalue}}}} of any non-function, non-array type {{tt|T}} can be implicitly converted to {{rev inl|until=c++11|an {{|value category#rvalue}}}}{{rev inl|since=c++11|a {{|value category#prvalue}}}}: | |||
{{rev inl|until=c++11|An {{ | |||
* If {{tt|T}} is not a class type, the type of the {{rev inl|until=c++11|rvalue}}{{rev inl|since=c++11|prvalue}} is the cv-unqualified version of {{tt|T}}. | * If {{tt|T}} is not a class type, the type of the {{rev inl|until=c++11|rvalue}}{{rev inl|since=c++11|prvalue}} is the cv-unqualified version of {{tt|T}}. | ||
* Otherwise, the type of the {{rev inl|until=c++11|rvalue}}{{rev inl|since=c++11|prvalue}} is {{tt|T}}. | * Otherwise, the type of the {{rev inl|until=c++11|rvalue}}{{rev inl|since=c++11|prvalue}} is {{tt|T}}. | ||
If an lvalue-to-rvalue conversion from an {{ | If an lvalue-to-rvalue conversion from an {{|type#Incomplete type}} is required by a program, that program is ill-formed. | ||
{{rev begin}} | {{rev begin}} | ||
{{rev|until=c++11| | {{rev|until=c++11| | ||
When an lvalue-to-rvalue conversion occurs within the operand of {{rlpt|sizeof}}, the value contained in | When an lvalue-to-rvalue conversion occurs within the operand of {{rlpt|sizeof}}, the value contained in is not accessed, since that operator {{rlp|expressions#Potentially-evaluated expressions|does not evaluate}} its operand | ||
. | |||
}} | }} | ||
{{rev|since=c++11| | {{rev|since=c++11| | ||
When an lvalue-to-rvalue conversion is applied to an expression {{c|E}}, the value contained in | When an lvalue-to-rvalue conversion is applied to an expression {{c|E}}, the value contained in is not accessed if: | ||
* {{c|E}} is not {{rlp|expressions#Potentially-evaluated expressions|potentially evaluated}}, or | * {{c|E}} is not {{rlp|expressions#Potentially-evaluated expressions|potentially evaluated}}, or | ||
* the evaluation of {{c|E}} results in the evaluation of a member {{c|Ex}} of the set of {{rlp|definition#ODR-use|potential results}} of {{c|E}}, and {{c|Ex}} names a variable {{c|x}} that is not {{rlp|definition#ODR-use|odr-used}} by {{c|Ex}}. | * the evaluation of {{c|E}} results in the evaluation of a member {{c|Ex}} of the set of {{rlp|definition#ODR-use|potential results}} of {{c|E}}, and {{c|Ex}} names a variable {{c|x}} that is not {{rlp|definition#ODR-use|odr-used}} by {{c|Ex}}. | ||
{{rev begin}} | {{rev begin}} | ||
{{rev|until=c++ | {{rev|until=c++| | ||
The result of the conversion is the | The result of the conversion is the . | ||
}} | }} | ||
{{rev|since | {{rev|since=c++17| | ||
::* conversion {{rlp|copy initialization|copy-initializes}} the [[#Temporary materialization|result object]] from the glvalue. | |||
: | |||
:* | |||
}} | }} | ||
* Otherwise, if | |||
* Otherwise, {{rev inl|since=c++20| | * Otherwise, if contains an invalid pointer value, the behavior is implementation-defined. | ||
* Otherwise, {{rev inl|since=c++20|is read, and}} the result is the value contained in the . | |||
}} | }} | ||
{{rev end}} | {{rev end}} | ||
| Line 134: | Line 140: | ||
====Array-to-pointer conversion==== | ====Array-to-pointer conversion==== | ||
{{anchor|Array to pointer conversion}}<!-- Keep the old links valid --> | {{anchor|Array to pointer conversion}}<!-- Keep the old links valid --> | ||
An {{ | An {{|value category#lvalue}} or {{|value category#rvalue}} of type of {{|N}} {{tt|T}}or of unknown bound of {{tt|T}}can be implicitly converted to a {{|value category#prvalue}} of type to {{tt|T}}. {{rev inl|since=c++17|If the array is a prvalue, #Temporary materializationoccurs.}} The resulting pointer refers to the first element of the array (see {{|array#Array-to-pointer decay | ||
|to pointer }} | |||
{{rrev|since=c++17| | {{rrev|since=c++17| | ||
====Temporary materialization==== | ====Temporary materialization==== | ||
A {{ | A {{|value category#prvalue}} of any complete type {{tt|T}} can be converted to an xvalue of the same type {{tt|T}}. This conversion initializes a {{rlp|lifetime#Temporary object lifetime|temporary object}} of type T from the prvalue by evaluating the prvalue with the temporary object as its result object, and produces an xvalue denoting the temporary object. | ||
If {{tt|T}} is a class or array of class type, it must have an accessible and non-deleted destructor. | If {{tt|T}} is a class or array of class type, it must have an accessible and non-deleted destructor. | ||
{{source|1= | {{source|1= | ||
| Line 145: | Line 156: | ||
// S() prvalue is converted to xvalue | // S() prvalue is converted to xvalue | ||
}} | }} | ||
Temporary materialization occurs in the following situations: | Temporary materialization occurs in the following situations: | ||
* when {{rlp|reference initialization|binding a reference}} to a prvalue; | * when {{rlp|reference initialization|binding a reference}} to a prvalue; | ||
* when | * when a | ||
{{rlp|operator member |member }} a class prvalue; | |||
* when performing an array-to-pointer conversion (see above) or {{rlp|operator member access#Built-in subscript operator|subscripting}} on an array prvalue; | * when performing an array-to-pointer conversion (see above) or {{rlp|operator member access#Built-in subscript operator|subscripting}} on an array prvalue; | ||
* when initializing an object of type {{ | * when initializing an object of type {{|std::initializer_list<T>}} from a {{rlp|initialization|braced-list}}; | ||
* when a prvalue appears as a {{rlp|expressions#Discarded-value expressions|discarded-value expression}}. | * when a prvalue appears as a {{rlp|expressions#Discarded-value expressions|discarded-value expression}}. | ||
Note that temporary materialization does ''not'' occur when initializing an object from a prvalue of the same type (by {{rlp|direct initialization|direct-initialization}} or {{rlp|copy initialization|copy-initialization}}): such object is initialized directly from the initializer. This ensures | Note that temporary materialization does ''not'' occur when initializing an object from a prvalue of the same type (by {{rlp|direct initialization|direct-initialization}} or {{rlp|copy initialization|copy-initialization}}): such object is initialized directly from the initializer. This ensures copy | ||
. | |||
}} | }} | ||
==== | ======== | ||
{{ | {{|to | ||
}} | |||
{{| | |||
|}} | |||
{{|}} | |||
{{rlp|#|}} | |||
{{|#|}} | |||
. | |||
{{|since=c++11| | |||
an unscoped enumeration type whose underlying type is fixed can be converted to its underlying type, 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 {{rlp|overload resolution}} | |||
}} | |||
- | |||
{{|}} {{c/core|}} {{c/core|}}. | |||
-point promotion. | |||
===Numeric conversions=== | ===Numeric conversions=== | ||
| Line 184: | Line 228: | ||
====Integral conversions==== | ====Integral conversions==== | ||
A {{ | A {{|value category#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 enwikiModular arithmetic|modulo{{math|2{{su|p=n}}}} where {{math|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 sign-extended<ref>This only applies if the arithmetic is two's complement which is only required for the [[cpp/types/integer|exact-width integer types]]. Note, however, that at the moment all platforms with a C++ compiler use two's complement arithmetic</ref> or truncated and unsigned integers are zero-extended 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 {{rev inl|until=c++20|implementation-defined}}{{rev inl|since=c++20|the unique value of the destination type equal to the source value modulo {{math|2{{su|p=n}}}} where {{math|n}} is the number of bits used to represent the destination type}} (that this is different from {{rlp|operator arithmetic#Overflows|signed integer arithmetic overflow}}, which is undefined). | |||
* If the source type is {{c/core|bool}}, the value {{c|false}} is converted to zero and the value {{c|true}} is converted to the value one of the destination type (note that if the destination type is {{c/core|int}}, this is an integer promotion, not an integer conversion). | |||
* If the destination type is {{c/core|bool}}, this is a [[#Boolean conversions|boolean conversion]] (see below). | |||
====Floating-point conversions==== | ====Floating-point conversions==== | ||
A {{ | |||
A {{|value category#prvalue | |||
|prvalue}} of a floating-point type can be converted to a prvalue of any other floating-point type . | |||
If the conversion is listed under floating-point 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 implementation-defined which one, although if IEEE arithmetic is supported, rounding defaults [[cpp/numeric/fenv/FE_round|to nearest]]). | |||
* Otherwise, the behavior is undefined. | |||
====Floating–integral conversions==== | ====Floating–integral conversions==== | ||
A {{|value category#prvalue}} of floating-point 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 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 {{c/core|bool}}, this is a boolean conversion (see below). | |||
A prvalue of integer or unscoped enumeration type can be converted to a prvalue of any floating-point 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 [[cpp/numeric/fenv/FE_round|to nearest]]. | |||
If the value cannot fit into the destination type, the behavior is undefined. | |||
If the source type is {{c/core|bool}}, the value {{c|false}} is converted to zero, and the value {{c|true}} is converted to one. | |||
====Pointer conversions==== | ====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 cv-qualified type as a single conversion, that is, it not considered a combination of numeric and qualifying conversions. | |||
A {{|value category#prvalue}} pointer to any (optionally cv-qualified) object type {{tt|T}} can be converted to a prvalue pointer to (identically cv-qualified) {{c/core|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 to (cv-qualified) can be converted to a prvalue to (cv-qualified) base class. If the is inaccessible or ambiguous, the is ill-formed. | |||
result is a pointer | |||
base classwithin the . | |||
pointer to the of the . | |||
====Pointer-to-member conversions==== | ====Pointer-to-member conversions==== | ||
A null pointer constant}} can be converted to any pointer-to-member 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 cv-qualified type as a single conversion, that is, it not considered a combination of numeric and qualifying conversions. | |||
A {{|value category#prvalue}} to member of {{tt|}} {{tt|}}can be converted to a {{|}} of type {{tt|T}}class {{tt|}} . If {{tt|}} is inaccessible, ambiguous, or virtual base of {{tt|}} or is a base of some intermediate virtual base of {{tt|}}, the is ill-formed. | |||
resulting pointer can be dereferenced with a {{tt|}} object, and it will access the member within the {{tt|}} base subobject of that {{tt|}} object. | |||
====Boolean conversions==== | ====Boolean conversions==== | ||
A {{ | A {{|value category#prvalue}} of integral, floating-point, unscoped enumeration, pointer, and pointer-to-member types can be converted to a prvalue of type {{c/core|bool}}. | ||
The value zero (for integral, floating-point, and unscoped enumeration) and the null pointer and the null pointer-to-member values become {{c|false}}. All other values become {{c|true}}. | The value zero (for integral, floating-point, and unscoped enumeration) and the null pointer and the null pointer-to-member values become {{c|false}}. All other values become {{c|true}}. | ||
| Line 220: | Line 293: | ||
===Qualification conversions=== | ===Qualification conversions=== | ||
:* A {{ | : | ||
* A {{|value category#prvalue}} of type pointer to {{rlp|cv|cv-qualified}} type {{tt|T}} can be converted to a prvalue pointer to a more cv-qualified same type {{tt|T}} (in other words, constness and volatility can be added). | |||
* A prvalue of type pointer to member of cv-qualified type {{tt|T}} in class {{tt|X}} can be converted to a prvalue pointer to member of more cv-qualifiedtype {{tt|T}} in class {{tt|X}}. | |||
cv- | |||
'''' | |||
type | |||
to to | |||
{{c/core|const }} ; | |||
*{{c/core|}} ; | |||
*{{c/core|const }} ; | |||
*{{c/core|const}} {{c/core|}} ; | |||
*{{c/core|}} {{c/core|const }} | |||
. | |||
-a {{tt|}} is {{|{{||}} }}- | |||
{{|{{||}} | |||
{{ | }} | ||
to | |||
. | |||
{{|cv{{| | |||
= | |||
n - | |||
1 | |||
= 1 | |||
}} }} - | |||
{{|{{|=|}} }} | |||
- | |||
{{tt|}} is {{tt|}} | |||