2012-03-28 8 views
4

私はVisual C++ 10では、引数の少なくとも1つがラムダであるときにADLが失敗することに気付きました。ラムダ引数があるとADLが失敗しますか?

std::vector<float> vec; 
for_each(begin(vec), end(vec), [](float) {}); 

上記はVC++ 10および11(ベータ版)でコンパイルできません(開始点と終了点はADLで見つかります)。ラムダ関数を通常のフリー関数に変換すると、期待通りに動作します。

私はHerb Suttersのブログで一度尋ねたことがあります。また、msdn connectに関するいくつかの記事を読んでいます。これはバグです.Lambdaの最新の標準を実装していません。理解できる。ものはまだ焼いた形ではありませんでした。 MS接続では、次のリリース、つまりvc 11では解決されないという邪魔なコメントもあります。

私の質問はです。はC++ 11標準で動作すると思われますか?私はそれを理解できない。私は本当に私のfor_eachと他のアルゴリズムのstd ::に接頭辞を付ける必要がありますか?lambdasを使用していますか? 私は何とかこの動作がvC++ 11のリリース後も変更されないと思われます。

+1

行う無料何の機能あなたが使う? –

+0

void f(float){}のような単純なものでも動作します。または関数呼び出しの外側にラムダを宣言します:auto f = [](float){}; –

答えて

1

これは完全に有効なコードです。バグのないコンパイラであればコンパイルできます。しかし、MSVCにはバグがあり、ADLを介して関数を検索することができないので、ADLに頼ってはならず、代わりにstd::で修飾して関数を見つけるのを助けてください。

+0

私は何を考えていたかを確認します。私はまた、ラムダ引数と非ラムダ引数の組み合わせがADLを無効にするべき理由を理解していません。私は公式のマイクロソフトの回答が好きかどうかはわかりません(ラムダを他の場所でインスタンス化するかstdで修飾するか::); –

+0

@Martin:いいえ、ベクトル :: iterator'は 'T *'にすることができます正確に問題)。 @ refpの答えは少し長いですが、あなたの疑惑を確認していませんが、それは正しいです。しかし、なぜそれが 'std'型よりもパラメータ化されていない自由な関数で動作するのか説明できません。 – Potatoswatter

+1

@Martin緑のチェックマークをrefpの答えに移動してください。 –

15

標準は、あなたがしたいと思うものを保証するものではありません、それまで..下の心の中で私たちは簡単にADLが提供される例に類似のケースでうまくいくことを保証は何もないことを認識することができますして

あなたの投稿に


  • std::begin (c)/std::end (c)

    関数は以下のように引用規格に記載されている:(c.begin()の戻り型である)Container<...>::iteratorであるが

    template <class C> auto begin(C& c) -> decltype(c.begin()); 
    template <class C> auto end(C& c) -> decltype(c.end()); 
    

    実装定義のタイプです。

    問題についての詳細は、24.5.6レンジアクセス、および23.3.6.1/2クラステンプレートベクトル(または任意の他のテンプレートSTLコンテナ)で時に読み込むことができます。

  • [](){} - ラムダ式

    ラムダは実装定義得られたオブジェクトが名前空間std下にあるタイプのものであろうことを示す規格に何もない、タイプ。

    標準で設定されている他のルールで確認されていれば、どこにいてもほとんど存在します。



長すぎます。 std::begin/std::end/a lambda-expression利回りは、したがって、ADLががで蹴ることが保証されていない名前空間std、下であることが保証されていないの

種類を読んでいない。

+3

@David:いいえ、問題はちょうど 'for_each'です。 'begin'と' end'は問題なく見つかったとさえ言います。私はほとんどの人が質問を正しく読まなかったと思います。 refp:+1の場合、これは正解です。 – Xeo

+0

@ Xeo:私はADLが 'begin'と' end'を解決できないと考えました。いずれにしても、標準ではイテレータが 'std'になるという保証はないので、ラムダの場合には' for_each'を見つけられないというバグがあります( 'std :: vector (std :: vector <> :: iterator'が 'stdの内部で定義されていない場合には(' ':: iterator'は' std'で定義されます)、またはADLが '' for_each''を見つけると、 ')。 –

+0

明確にするために:beginとendは、vC++ 10と11の両方のベータ版でADLを使って正しく解決されています。私の質問は、なぜnamespace std *と* 1つ以上のlambdaからのタイプの組み合わせがある場合にfor_each(または他のstdアルゴリズム)のADLが失敗するかを指していました。私は、vC++はlambda引数があるときにADLを無効にすると思います。 for_each関数呼び出しの外で宣言されているlambdaをfor_eachに渡すと、ADLは動作します(現在のところ、Microsoftの正式な回避策です)。 –

関連する問題