4

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

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

上記は VC++10 および 11 (ベータ) でのコンパイルに失敗します (begin と end は ADL を介して検出されます)。ラムダ関数を通常の自由関数に変換すると、期待どおりに機能します。

Herb Sutters ブログで 1 回質問したことがあり、msdn connect の投稿も読んだことがありますが、通常の回答は次のとおりでした。これはバグです。ラムダの最新の標準をまだ実装していません。物事はまだ焼きたての形になっていません。MS Connect では、これが次のリリース、つまり vc 11 で解決されないという不穏なコメントもありました。

私の質問は、このコードは C++11 標準で動作すると予想されますか? 私はそれを完全に理解することはできません。ラムダを使用している場合、for_each やその他のアルゴリズムの前に std:: を付ける必要がありますか? この動作は vc++11 のリリース後も変わらないのではないかと思います。

4

2 に答える 2

15

標準は、あなたが望むものを保証するものではありません..

以下を念頭に置いて、投稿で提供されている例と同様のケースでADLが機能することを保証するものは何もないことを簡単に理解できます.


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

    関数は、以下の引用として標準で説明されています。

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

    (の戻りContainer< ... >::iterator値の型であるc.begin ())は実装定義の型ですが。

    この問題の詳細については、24.5.6 Range Accessおよび23.3.6.1/2 クラス テンプレート ベクトル(またはその他のテンプレート STL コンテナー) を参照してください。

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

    ラムダは実装定義の型です。結果のオブジェクトが名前空間 stdの下にある型になることを示す標準には何もありません。

    標準によって設定された他のルールに準拠している限り、ほとんどどこにでも存在できます。



長すぎる; 読まなかった

std::begin//生成される型が名前空間 stdの下にあることが保証されていないstd::endため、ADL が開始されることが保証されていません。a lambda-expression

于 2012-03-28T02:02:22.113 に答える
1

これは完全に有効なコードです。バグのないコンパイラならどれでもコンパイルできます。ただし、MSVC にはバグがあり、ADL を介して関数を検索できないため、ADL に依存するのではなくstd::、コンパイラが関数を見つけるのを支援することで修飾する必要があります。

于 2012-03-28T01:32:01.633 に答える