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);
_
これは単にMSVCが遅れているだけです。C++ 03のルールは、整数型と値0のany定数式はnullポインター定数であり、_char*
_に変換できるというものでした。確かにchar()
は適格であり、_char{}
_は同じことを意味しますが、ルールと重複することはありません。
ビジュアルはたくさんあるからです。特に古いもの。コードは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で確認してみてください。