MSVC是否有权找到这种方法称之为含糊不清,而Clang / GCC不是吗?

时间:2017-02-27 07:44:27

标签: c++ gcc visual-c++ clang language-lawyer

Clang(3.9.1)和GCC(7,快照)print" 1"," 2"运行此代码时到控制台。

但是,MSVC无法编译此代码:

  

source_file.cpp(15):错误C2668:'字典::设置':对重载函数的模糊调用

     

source_file.cpp(9):注意:可能是' void Dictionary :: set(int64_t)'

     

source_file.cpp(8):注意:或' void Dictionary :: set(const char *)'

     

source_file.cpp(15):注意:尝试匹配参数列表'(const unsigned int)'

#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);
  

source_file.cpp:15:10:错误:调用成员函数&#39;设置&#39;很暧昧       dict.set(0);

     

source_file.cpp:8:10:注意:候选函数

void set(const char *Str) { std::cout << "1"; }
     

source_file.cpp:9:10:注意:候选函数

void set(int64_t val) { std::cout << "2"; }

那么这里发生了什么 - 哪个编译器是对的?如果GCC和Clang都接受错误的代码,或者MSVC是否有错误,我会感到惊讶吗?请参阅标准

2 个答案:

答案 0 :(得分:4)

在C ++ 11及之前,任何整型常量表达式的计算结果为0都被视为空指针常量。这在C ++ 14中受到限制:只考虑值为0的整数文字。此外,类型std::nullptr_t的prvalues是自C ++ 11以来的空指针常量。见[conv.ptr]和CWG 903

关于重载分辨率,整数转换unsigned - &gt; int64_t和指针转换空指针常量 - &gt; 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是正确的。

答案 1 :(得分:1)

当两个编制者同意而一个人没有同意时,它几乎总是那个没有错误的编制者。

我认为如果你将一个值声明为const unsigned somename = 0;,它就不再是一个简单的零,它是一个名为无符号常量,其值为零。所以不应该被认为等同于指针类型,只留下一个合理的候选人。

话虽如此,set函数的两个函数都需要转换(它不是uint64_t,也不是const char *),所以可以说MSVC是正确的[编译器应选择需要最少转换的类型,如果多个类型需要相同的转换量,则它是不明确的 - 尽管我仍然认为编译器不应接受零值的命名常量作为相当于一个指针......

对不起,可能更多的是&#34;评论&#34;而不是答案 - 我开始写作的目的是说&#34; gcc / clang是对的&#34;,但后来更多地考虑它得出结论&#34;虽然我会对这种行为感到高兴,但它& #39;不清楚这是正确的行为&#34;。