gpt4 book ai didi

c++ - 与 const 枚举值 0 匹配的 MSVC 函数

转载 作者:塔克拉玛干 更新时间:2023-11-02 23:33:39 27 4
gpt4 key购买 nike

我被 MSVC 意外的 C++ 函数匹配所困扰。我可以将其简化为以下测试用例:

#include <iostream>

enum Code { aaa, bbb };

struct MyVal {
Code c;
MyVal(Code c): c(c) { }
};

void test(int i, MyVal val) {
std::cout << "case " << i << ": value " << val.c << std::endl;
}

void test(int i, double* f) {
std::cout << "case " << i << ": WRONG" << std::endl;
}

const Code v1 = aaa;
Code v2 = aaa;
const Code v3 = bbb;

int main() {
const Code w1 = aaa;
Code w2 = aaa;
const Code w3 = bbb;

test(1, v1); // unexpected MSVC WRONG
test(2, v2);
test(3, v3);
test(4, aaa);
test(5, w1); // unexpected MSVC WRONG
test(6, w2);
test(7, w3);
return 0;
}

我预计 test 的所有 7 次调用都将匹配第一个重载,并且 GCC ( live example ) 和 Clang ( live example ) 按预期匹配:

case 1: value 0
case 2: value 0
case 3: value 1
case 4: value 0
case 5: value 0
case 6: value 0
case 7: value 1

但 MSVC ( live example ) 将情况 1 和 5 与“错误”重载相匹配(我在 MSVC 2013 和 2015 中发现了这种行为):

case 1: WRONG
case 2: value 0
case 3: value 1
case 4: value 0
case 5: WRONG
case 6: value 0
case 7: value 1

对于具有(意外)值 0 的 const 枚举变量,似乎 MSVC 更喜欢转换为指针。我本以为这是文字 0 的行为,但不是枚举变量。

我的问题:MSVC 行为是否符合标准? (可能适用于旧版本的 C++?)如果不是,这是已知的扩展或错误吗?

最佳答案

你没有说出任何标准,但让我们看看有什么区别:

[C++11: 4.10/1]: A null pointer constant is an integral constant expression (5.19) prvalue of integer type that evaluates to zero or a prvalue of type std::nullptr_t. A null pointer constant can be converted to a pointer type; the result is the null pointer value of that type and is distinguishable from every other value of object pointer or function pointer type. Such a conversion is called a null pointer conversion. Two null pointer values of the same type shall compare equal. The conversion of a null pointer constant to a pointer to cv-qualified type is a single conversion, and not the sequence of a pointer conversion followed by a qualification. [..]

[C++11: 5.19/3]: A literal constant expression is a prvalue core constant expression of literal type, but not pointer type. An integral constant expression is a literal constant expression of integral or unscoped enumeration type. [..]

和:

[C++03: 4.10/1]: A null pointer constant is an integral constant expression (5.19) rvalue of integer type that evaluates to zero. A null pointer constant can be converted to a pointer type; the result is the null pointer value of that type and is distinguishable from every other value of pointer to object or pointer to function type. Two null pointer values of the same type shall compare equal. The conversion of a null pointer constant to a pointer to cv-qualified type is a single conversion, and not the sequence of a pointer conversion followed by a qualification conversion (4.4).

[C++03: 5.19/2]: Other expressions are considered constant-expressions only for the purpose of non-local static object initialization (3.6.2). Such constant expressions shall evaluate to one of the following:

  • a null pointer value (4.10),
  • a null member pointer value (4.11),
  • an arithmetic constant expression,
  • an address constant expression,
  • a reference constant expression,
  • an address constant expression for a complete object type, plus or minus an integral constant expression, or
  • a pointer to member constant expression.

这里的关键是标准语言在 C++03 和 C++11 之间发生了变化,后者引入了这种形式的空指针常量必须是文字的要求。

(它们实际上始终需要是常量并评估为 0,因此您可以删除 v2v3w2 w3 来自你的测试用例。)

空指针常量可以比通过用户定义的转换更容易地转换为 double*,所以……

我相信 MSVS 正在实现 C++03 规则。

有趣的是,如果我将 GCC 置于 C++03 模式,它的行为不会改变,这在技术上是不兼容的。我怀疑语言的变化源于当时常见实现的行为,而不是相反。我可以看到一些 evidence that GCC was [allegedly] non-conforming in this regard as early as 2004 ,所以也可能只是标准措辞的改变偶然地取消了 GCC 错误。

关于c++ - 与 const 枚举值 0 匹配的 MSVC 函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41058178/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com