C++ 是否保证此枚举与 int 构造函数重载解析?
Does C++ guarantee this enum vs int constructor overload resolution?
考虑这个示例程序:
#include <iostream>
typedef enum { A, B, C } MyEnum;
struct S
{
S(int) { std::cout << "int" << std::endl; }
S(MyEnum) { std::cout << "MyEnum" << std::endl; }
};
S f()
{
return A;
}
int main()
{
S const s = f();
}
用 clang 和 gcc 编译,这会生成一个可执行文件,在 运行 时打印“MyEnum”。 C++ 标准保证这种行为吗?
当然可以。 return
语句允许隐式构造并且 S(MyEnum)
是完全匹配。
同样适用于 return {A};
但是如果你要S(MyEnum)
明确,那么:
return A;
将调用 S(int)
作为回退,因为 MyEnum
可以隐式转换为整数。但由于额外的转换,这比 S(MyEnum)
更糟糕的重载候选者,仅根据需要选择。
return {A};
表示复制列表初始化。它会失败,因为它禁止显式构造函数和隐式转换。
return S{A};
表示direct-list初始化,会调用S(MyEnum)
,虽然限制了一些隐式转换,但不影响本例和S(int)
将被调用 S(MyEnum)
被删除。
return S(A);
本质上与 return A;
相同,给定指定的 return 类型 S
.
是的,S::S(MyEnum)
在 overload resolution because it's an exact match. While S::S(int)
requires one more implicit conversion (integral promotion) 中获胜,从枚举到 int
。
Each type of standard conversion sequence is assigned one of three ranks:
- Exact match: no conversion required, lvalue-to-rvalue conversion, qualification > conversion, function pointer conversion, (since C++17) user-defined conversion of class type to the same class
- Promotion: integral promotion, floating-point promotion
- Conversion: integral conversion, floating-point conversion, floating-integral conversion, pointer conversion, pointer-to-member conversion, boolean conversion, user-defined conversion of a derived class to its base
A standard conversion sequence S1 is better than a standard conversion sequence S2 if
a) S1 is a subsequence of S2, excluding lvalue transformations. The identity conversion sequence is considered a subsequence of any other conversion
b) Or, if not that, the rank of S1 is better than the rank of S2
F1 is determined to be a better function than F2 if implicit conversions for all arguments of F1 are not worse than the implicit conversions for all arguments of F2, and
- there is at least one argument of F1 whose implicit conversion is better than the corresponding implicit conversion for that argument of F2
These pair-wise comparisons are applied to all viable functions. If exactly one viable function is better than all others, overload resolution succeeds and this function is called. Otherwise, compilation fails.
考虑这个示例程序:
#include <iostream>
typedef enum { A, B, C } MyEnum;
struct S
{
S(int) { std::cout << "int" << std::endl; }
S(MyEnum) { std::cout << "MyEnum" << std::endl; }
};
S f()
{
return A;
}
int main()
{
S const s = f();
}
用 clang 和 gcc 编译,这会生成一个可执行文件,在 运行 时打印“MyEnum”。 C++ 标准保证这种行为吗?
当然可以。 return
语句允许隐式构造并且 S(MyEnum)
是完全匹配。
同样适用于 return {A};
但是如果你要S(MyEnum)
明确,那么:
return A;
将调用S(int)
作为回退,因为MyEnum
可以隐式转换为整数。但由于额外的转换,这比S(MyEnum)
更糟糕的重载候选者,仅根据需要选择。return {A};
表示复制列表初始化。它会失败,因为它禁止显式构造函数和隐式转换。return S{A};
表示direct-list初始化,会调用S(MyEnum)
,虽然限制了一些隐式转换,但不影响本例和S(int)
将被调用S(MyEnum)
被删除。return S(A);
本质上与return A;
相同,给定指定的 return 类型S
.
是的,S::S(MyEnum)
在 overload resolution because it's an exact match. While S::S(int)
requires one more implicit conversion (integral promotion) 中获胜,从枚举到 int
。
Each type of standard conversion sequence is assigned one of three ranks:
- Exact match: no conversion required, lvalue-to-rvalue conversion, qualification > conversion, function pointer conversion, (since C++17) user-defined conversion of class type to the same class
- Promotion: integral promotion, floating-point promotion
- Conversion: integral conversion, floating-point conversion, floating-integral conversion, pointer conversion, pointer-to-member conversion, boolean conversion, user-defined conversion of a derived class to its base
A standard conversion sequence S1 is better than a standard conversion sequence S2 if
a) S1 is a subsequence of S2, excluding lvalue transformations. The identity conversion sequence is considered a subsequence of any other conversion
b) Or, if not that, the rank of S1 is better than the rank of S2
F1 is determined to be a better function than F2 if implicit conversions for all arguments of F1 are not worse than the implicit conversions for all arguments of F2, and
- there is at least one argument of F1 whose implicit conversion is better than the corresponding implicit conversion for that argument of F2
These pair-wise comparisons are applied to all viable functions. If exactly one viable function is better than all others, overload resolution succeeds and this function is called. Otherwise, compilation fails.