运行此代码时,Clang(3.9.1)和GCC(7,快照)将“1”,“2”打印到控制台。
但是,MSVC无法编译此代码:
#include <iostream>
static const unsigned ProtocolMajorVersion = 1;
static const unsigned ProtocolMinorVersion = 0;
class Dictionary {
public:
void set(const char *Str) { std::cout << "1"; }
void set(int64_t val) { std::cout << "2"; }
};
int main() {
Dictionary dict;
dict.set(ProtocolMajorVersion);
dict.set(ProtocolMinorVersion);
}
我认为MSVC是正确的-
ProtocolMajorVersion
的值是0
,可以是NULL
或int64_t(0)
。但是,更换时似乎是这种情况
dict.set(ProtocolMinorVersion)
与
dict.set(0);
那么,这是怎么回事-哪个编译器正确?如果GCC和Clang都接受了不正确的代码,或者MSVC只是 buggy ,会让我感到惊讶吗?请引用标准
最佳答案
在C++ 11及更低版本中,任何求值为0的整数常量表达式都被视为空指针常量。这在C++ 14中受到限制:仅考虑值为0的整数文字。另外,从C++ 11开始,std::nullptr_t
类型的prvalue是空指针常量。参见[conv.ptr]和CWG 903。
关于重载分辨率,整数转换unsigned
-> int64_t
和指针转换null指针常量-> const char*
都具有相同的等级:转换。参见[over.ics.scs] /表12。
因此,如果将ProtocolMinorVersion
视为空指针常量,则这些调用是不确定的。如果仅编译以下程序:
static const unsigned ProtocolMinorVersion = 0;
int main() {
const char* p = ProtocolMinorVersion;
}
您将看到clang和gcc拒绝此转换,而MSVC接受它。
由于CWG 903被认为是缺陷,因此我认为clang和gcc是正确的。
关于c++ - MSVC是否正确找到此方法调用不明确,而Clang/GCC却不正确?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/42480247/