2017-01-18 8 views
46
#include <iostream> 

void IsTrue(const bool value) { 
    if (value) { 
    std::cout << "value is True!\n"; 
    } 
} 

int main() 
{ 
    IsTrue([]() { ; /* some lambda */ }); 

    return 0; 
} 

出力:ラムダが値が真であるブールに変換するのはなぜですか?

value is True! 

はなぜラムダはGCC &クランにtrueに評価されていますか? MSVCはこれを構築できません(ラムダをブールに変換できません)。

コンパイラのバグですか?または、標準のどの段落でこれが許されていますか?

+11

これが合法であるかどうかわからないが、ラムダを関数ポインタに変換し、その値(ヌルでない)をブールに使用してコンパイルするように見えるかどうかはわかりません。キャプチャを追加すると[コンパイルに失敗します](http://coliru.stacked-crooked.com/a/f28beac0173e86e4)。 – NathanOliver

+8

MSVCには[非標準的な拡張機能](https://adishavit.github.io/2016/magical-captureless-lambdas/)があります。そのため、宛先関数のポインタ型を明示的に指定する必要があります。そうしないと、変換は失敗します。 – cpplearner

+0

[関数ポインタとしてラムダを渡す]も参照してください(http://stackoverflow.com/q/28746744/1708801) –

答えて

44

C++ 14標準(5.1.2)は言う:

なし と非ジェネリックラムダ式の閉じ方の種類は、ラムダキャプチャは公共非があります-virtual非明示的const変換 関数へのポインタへの関数 C++言語のリンケージ(7.5) と同じパラメータと戻り値の型は、クロージャ型の 関数呼び出し演算子と同じです。この変換関数 によって返される値は、呼び出されるとクロージャー型の関数呼び出し演算子を呼び出すのと同じ の効果を持つ関数のアドレスになります。

関数ポインタは暗黙的にboolに変換されるので、表示された結果が得られます。これは完全に合法です。

この変換演算子に異なる呼び出し規約(__stdcall,など)がオーバーロードされているため、MSVCはこれをコンパイルしません。 x64のコンパイルでは、これらの呼び出し規則はすべて使用されないため、変換演算子は1つだけで、コンパイルは正常に行われます。

関連する問題