运行此代码时,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,可以是NULLint64_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/

10-09 15:51
查看更多