🌟
MSVC + std::shared_ptr で false が通ってしまう
std::shared_ptr<int> myfun() {
return false;
}
int main() {
std::shared_ptr<int> a = myfun();
if(!a) {
std::puts("bora");
}
}
MSVC だとコンパイルが通る. clang/gcc だと
could not convert ‘false’ from ‘bool’ to ‘std::shared_ptr<int>' ...
とエラーが出る.
return 0
とすると両方でコンパイルが通る.
MSVC は false
を 0 で定義しているため?
理想は?
nullptr がよいようであるが, なんかややこしい... 0
がよかったりするんじゃろか?
Discussion
手元で試したところ Visual Studio 2019 のビルドツールである MSVC v142 からは適切にエラーとなるようです
それ以前のビルドツールでは
std::nullptr_t
がfalse
から変換できてしまったためにコンパイルが通っていましたこれは欠陥報告が上がって修正された C++ の仕様側の変更に対しての修正が遅れたのだと思います。 古い C++ では「値がゼロの整数定数式は空ポインタリテラルとして使える」というルール (おそらく C の規則をそのまま真似した) があり、
bool
は整数型の一種なのでこのルールだとfalse
は空ポインタとして解釈しうるはずです。現在の C++ はリテラルの
0
に限って空ポインタとして解釈するように改められています。ありがとうございます!
compiler explorer では MSVC v19(VS2024?)でもコンパイルできていました...
いずれにせよ false はよくなくて, 理想は
nullptr
でしょうか..どうコードを書くべきかという観点のお話でしたら、暗黙のオブジェクト構築に依存せずに、
デフォルトコンストラクターで空のスマートポインタを返すのが明確で良いのではないかと思います。
Move Semantics なり、Return Value Optimization なりで、
問題になるようなレベルの性能劣化は怒らないと思います。
何度も長い型名をタイプしたくないということでしたら、
auto
を使って逃げる手もありますね。型の間違いチェックのために明示したい事とのトレードオフですが。
なるほど! ありがとうございます!
MSVCでのC++17指定のコンパイラオプションは
-std=c++17
ではなく-std:c++17
ですねMSVC だと
/std:c++17
ですね. 結果は同じ(コンパイルは通る)でした-
と/
は互換性のためどちらでも同じですが、確かにc++17
でも通りますね。c++20
だとエラーになりました。なんと! C++20 で厳格になったのかしらん?