了解非重载按位运算符的转换顺序、算术转换和整数提升
Understanding the order of conversions, arithmetic conversions, and integer promotions for non-overloaded bitwise operators
我想确切地了解发生了什么,当编译器遇到非重载运算符时以及操作了哪些转换。例如,让我们以按位运算符为例,例如 &
。标准说:
[expr.bit.and] The usual arithmetic conversions are performed; the result is the bitwise AND function of the operands. The operator applies only to integral or unscoped enumeration operands.
然后如果我正在搜索通常的算术转换,我得到:
[expr] Many binary operators that expect operands of arithmetic or enumeration type cause conversions and yield result types in a similar way. The purpose is to yield a common type, which is also the type of the result.
This pattern is called the usual arithmetic conversions, which are defined as follows:
- If either operand is of scoped enumeration type (7.2), no conversions are performed; if the other
operand does not have the same type, the expression is ill-formed.
- If either operand is of type long double, the other shall be converted to long double.
- Otherwise, if either operand is double, the other shall be converted to double.
- Otherwise, if either operand is float, the other shall be converted to float.
- Otherwise, the integral promotions shall be performed on both operands. Then the following rules shall be applied to the promoted operands:
- If both operands have the same type, no further conversion is needed.
- Otherwise, if both operands have signed integer types or both have unsigned integer types, the operand with the type of lesser integer conversion rank shall be converted to the type of the operand with greater rank.
- Otherwise, if the operand that has unsigned integer type has rank greater than or equal to the rank of the type of the other operand, the operand with signed integer type shall be converted to the type of the operand with unsigned integer type.
- Otherwise, if the type of the operand with signed integer type can represent all of the values of the type of the operand with unsigned integer type, the operand with unsigned integer type shall be converted to the type of the operand with signed integer type.
- Otherwise, both operands shall be converted to the unsigned integer type corresponding to the type of the operand with signed integer type
现在,如果我们看一下整数提升:
[conv.prom]:
- A prvalue of an integer type other than bool, char16_t, char32_t, or wchar_t whose integer conversion rank is less than the rank of int can be converted to a prvalue of type int if int can represent all the values of the source type; otherwise, the source prvalue can be converted to a prvalue of type unsigned int.
- A prvalue of type char16_t, char32_t, or wchar_t (3.9.1) 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 int, unsigned long int, long long int, or unsigned long long int. If none of the types in that list can represent all the values of its underlying type, a prvalue of type char16_t, char32_t, or wchar_t can be converted to a prvalue of its underlying type.
- A prvalue of an unscoped enumeration type whose underlying type is not fixed can be converted to a prvalue of the first of the following types that can represent all the values of the enumeration: int, unsigned int, long int, unsigned long int, long long int, or unsigned long long int. If none of the types in that list can represent all the values of the enumeration, a prvalue of an unscoped enumeration type can be converted to a prvalue of the extended
integer type with lowest integer conversion rank greater than the rank of long long in which all the values of the enumeration can be represented. If there are two such extended types, the signed one is chosen.
- A prvalue of an unscoped enumeration type whose underlying type is fixed can be converted to a prvalue of its underlying type. Moreover, if integral promotion can be applied to its underlying type, a prvalue of an unscoped enumeration type whose underlying type is fixed can also be converted to a prvalue of the promoted underlying type.
- A prvalue for an integral bit-field can be converted to a prvalue of type int if int can represent all the values of the bit-field; otherwise, it can be converted to unsigned int if unsigned int can represent all the values of the bit-field. If the bit-field is larger yet, no integral promotion applies to it. If the bit-field has an enumerated type, it is treated as any other value of that type for promotion purposes.
- A prvalue of type bool can be converted to a prvalue of type int, with false becoming zero and true becoming one.
- These conversions are called integral promotions.
但如果我们这样做:
std::integral_constant<int, 2> x;
std::integral_constant<int, 3> y;
int z = x & y;
它会起作用,虽然我没有看到它在标准中的什么地方被指定。我想确切地说,所有按顺序完成的转换检查。我认为首先,编译器会检查 operator& 是否有一个完全采用类型的重载。然后我不知道编译器做了什么其他测试。并且可能仅在此之后它才使用通常的算术转换,然后使用积分提升。
那么当编译器遇到 T1 & T2
时,编译器在做什么转换测试和步骤,以什么顺序进行? (欢迎从标准中摘录)。
当编译器看到这个时:
int z = x & y;
它会看到 std::integral_constant<>
没有特定的 operator &
。但是它将看到 x
和 y
有一个非 explicit
operator value_type()
。由于 value_type
是 int
,这给出了最常见的 operator &
.
的直接匹配
不需要或执行任何算术转换或整数提升。
[conv] (2.1) 说:
When used as operands of operators. The operator’s requirements for its operands dictate the destination type.
[over.match] 说:
Each of these contexts defines the set of candidate functions and the list of arguments in its own unique way.
But, once the candidate functions and argument lists have been identified, the selection of the best function
is the same in all cases:
- (2.8) — First, a subset of the candidate functions (those that have the proper number of arguments and meet
certain other conditions) is selected to form a set of viable functions (13.3.2).
- (2.9) — Then the best viable function is selected based on the implicit conversion sequences (13.3.3.1) needed
to match each argument to the corresponding parameter of each viable function.
[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 4), for
initialization (8.5), and for explicit type conversions (5.4, 5.2.9).
我想确切地了解发生了什么,当编译器遇到非重载运算符时以及操作了哪些转换。例如,让我们以按位运算符为例,例如 &
。标准说:
[expr.bit.and] The usual arithmetic conversions are performed; the result is the bitwise AND function of the operands. The operator applies only to integral or unscoped enumeration operands.
然后如果我正在搜索通常的算术转换,我得到:
[expr] Many binary operators that expect operands of arithmetic or enumeration type cause conversions and yield result types in a similar way. The purpose is to yield a common type, which is also the type of the result. This pattern is called the usual arithmetic conversions, which are defined as follows:
- If either operand is of scoped enumeration type (7.2), no conversions are performed; if the other operand does not have the same type, the expression is ill-formed.
- If either operand is of type long double, the other shall be converted to long double.
- Otherwise, if either operand is double, the other shall be converted to double.
- Otherwise, if either operand is float, the other shall be converted to float.
- Otherwise, the integral promotions shall be performed on both operands. Then the following rules shall be applied to the promoted operands:
- If both operands have the same type, no further conversion is needed.
- Otherwise, if both operands have signed integer types or both have unsigned integer types, the operand with the type of lesser integer conversion rank shall be converted to the type of the operand with greater rank.
- Otherwise, if the operand that has unsigned integer type has rank greater than or equal to the rank of the type of the other operand, the operand with signed integer type shall be converted to the type of the operand with unsigned integer type.
- Otherwise, if the type of the operand with signed integer type can represent all of the values of the type of the operand with unsigned integer type, the operand with unsigned integer type shall be converted to the type of the operand with signed integer type.
- Otherwise, both operands shall be converted to the unsigned integer type corresponding to the type of the operand with signed integer type
现在,如果我们看一下整数提升:
[conv.prom]:
- A prvalue of an integer type other than bool, char16_t, char32_t, or wchar_t whose integer conversion rank is less than the rank of int can be converted to a prvalue of type int if int can represent all the values of the source type; otherwise, the source prvalue can be converted to a prvalue of type unsigned int.
- A prvalue of type char16_t, char32_t, or wchar_t (3.9.1) 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 int, unsigned long int, long long int, or unsigned long long int. If none of the types in that list can represent all the values of its underlying type, a prvalue of type char16_t, char32_t, or wchar_t can be converted to a prvalue of its underlying type.
- A prvalue of an unscoped enumeration type whose underlying type is not fixed can be converted to a prvalue of the first of the following types that can represent all the values of the enumeration: int, unsigned int, long int, unsigned long int, long long int, or unsigned long long int. If none of the types in that list can represent all the values of the enumeration, a prvalue of an unscoped enumeration type can be converted to a prvalue of the extended integer type with lowest integer conversion rank greater than the rank of long long in which all the values of the enumeration can be represented. If there are two such extended types, the signed one is chosen.
- A prvalue of an unscoped enumeration type whose underlying type is fixed can be converted to a prvalue of its underlying type. Moreover, if integral promotion can be applied to its underlying type, a prvalue of an unscoped enumeration type whose underlying type is fixed can also be converted to a prvalue of the promoted underlying type.
- A prvalue for an integral bit-field can be converted to a prvalue of type int if int can represent all the values of the bit-field; otherwise, it can be converted to unsigned int if unsigned int can represent all the values of the bit-field. If the bit-field is larger yet, no integral promotion applies to it. If the bit-field has an enumerated type, it is treated as any other value of that type for promotion purposes.
- A prvalue of type bool can be converted to a prvalue of type int, with false becoming zero and true becoming one.
- These conversions are called integral promotions.
但如果我们这样做:
std::integral_constant<int, 2> x;
std::integral_constant<int, 3> y;
int z = x & y;
它会起作用,虽然我没有看到它在标准中的什么地方被指定。我想确切地说,所有按顺序完成的转换检查。我认为首先,编译器会检查 operator& 是否有一个完全采用类型的重载。然后我不知道编译器做了什么其他测试。并且可能仅在此之后它才使用通常的算术转换,然后使用积分提升。
那么当编译器遇到 T1 & T2
时,编译器在做什么转换测试和步骤,以什么顺序进行? (欢迎从标准中摘录)。
当编译器看到这个时:
int z = x & y;
它会看到 std::integral_constant<>
没有特定的 operator &
。但是它将看到 x
和 y
有一个非 explicit
operator value_type()
。由于 value_type
是 int
,这给出了最常见的 operator &
.
不需要或执行任何算术转换或整数提升。
[conv] (2.1) 说:
When used as operands of operators. The operator’s requirements for its operands dictate the destination type.
[over.match] 说:
Each of these contexts defines the set of candidate functions and the list of arguments in its own unique way. But, once the candidate functions and argument lists have been identified, the selection of the best function is the same in all cases:
- (2.8) — First, a subset of the candidate functions (those that have the proper number of arguments and meet certain other conditions) is selected to form a set of viable functions (13.3.2).
- (2.9) — Then the best viable function is selected based on the implicit conversion sequences (13.3.3.1) needed to match each argument to the corresponding parameter of each viable function.
[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 4), for initialization (8.5), and for explicit type conversions (5.4, 5.2.9).