web-dev-qa-db-ja.com

char {}とchar()がchar *引数の一時変数として機能するのはなぜですか?

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());
_

_char*_またはchar()が引数として使用されている場合、コンパイラーはどのようにcharを_char{}_に推定(または変換)しますか?

charと_char*_の両方のオーバーロードがある場合、あいまいさに関するエラーや警告なしに機能します。

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

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

コンパイラがTakePtr(char*)に対して_char{}_を使用しても問題ないのはなぜですか?そして、なぜbetterバージョンを選択するときに警告/エラーを出さないのですか?このような動作は、既存のコードを破壊することにつながります。

確かに、コンパイラーは以下に満足していません。

_void TakePtr(char*);

    char c{};
    TakePtr(c);
_
18
Ajay

これは単にMSVCが遅れているだけです。C++ 03のルールは、整数型と値0のany定数式はnullポインター定数であり、_char*_に変換できるというものでした。確かにchar()は適格であり、_char{}_は同じことを意味しますが、ルールと重複することはありません。

3
Davis Herring

ビジュアルはたくさんあるからです。特に古いもの。コードは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で確認してみてください。

13