18

在 Visual C++ 2017(带有/std:c++14或带有/std:c++17)中,以下代码有效:

void TakePtr(char*); // const or not

int main()
{ 
     TakePtr(char{});
     TakePtr(char());
}

我不明白为什么它有效。

显然,以下内容也将起作用(如预期的那样):

void TakeChar(char);

   TakeChar(char{});
   TakeChar(char());

编译器如何将类型推断(或转换)charchar*、 何时char{}char()用作参数?

现在,如果我同时拥有charchar*重载,它的工作原理不会出现任何关于歧义的错误/警告:

void TakePtr(char*);
void TakePtr(char);

    TakePtr(char{});  // Chooses 'char'
    TakePtr(char());  // Chooses 'char'

为什么编译器可以使用char{}for TakePtr(char*)为什么在选择更好的版本时不给出警告/错误?这种行为势必会破坏现有代码。

当然,编译器不满意:

void TakePtr(char*);

    char c{};
    TakePtr(c);
4

2 回答 2

13

因为视觉谎言很多。尤其是年纪大的。你的代码提示clang报错:

<source>:9:6: error: no matching function for call to 'TakePtr'

     TakePtr(char{});

     ^~~~~~~

<source>:5:6: note: candidate function not viable: no known conversion from 'char' to 'char *' for 1st argument

void TakePtr(char*); // const or not

     ^

<source>:10:6: error: no matching function for call to 'TakePtr'

     TakePtr(char());

     ^~~~~~~

<source>:5:6: note: candidate function not viable: no known conversion from 'char' to 'char *' for 1st argument

void TakePtr(char*); // const or not

     ^

2 errors generated.

众所周知,Visual 在遵循 C++ 标准方面是“古怪的”,所以不要过分依赖它。尝试使用 clang/gcc 进行验证,以确保确定。

于 2019-06-21T11:34:56.453 回答
3

这只是 MSVC 落后了:C++03 中的规则是任何整数类型和值 0 的常量表达式都是空指针常量,因此可以转换为char*. 当然char()有资格——并且char{}意味着同样的事情,尽管它从未与规则重叠。

于 2019-06-22T00:15:08.553 回答