64

どのスタイルが好まれるかについて質問があります: std::bind Vs lambda in C++0x. それらが何らかの形で異なる目的を果たしていることは知っていますが、交差する機能の例を挙げてみましょう。

使用lambda:

uniform_int<> distribution(1, 6);
mt19937 engine;
// lambda style
auto dice = [&]() { return distribution(engine); };

使用bind:

uniform_int<> distribution(1, 6);
mt19937 engine;
// bind style
auto dice = bind(distribution, engine);

どちらを優先する必要がありますか? なぜ?上記の例と比較して、より複雑な状況を想定しています。すなわち、一方の長所と短所は何ですか?

4

7 に答える 7

47

C ++ 0xラムダは単形ですが、バインドは多形にすることができます。あなたは次のようなものを持つことはできません

auto f = [](auto a, auto b) { cout << a << ' ' << b; }
f("test", 1.2f);

aとbは既知のタイプである必要があります。一方、tr1 / boost / phoenix / lambda bindを使用すると、次のことが可能になります。

struct foo
{
  typedef void result_type;

  template < typename A, typename B >
  void operator()(A a, B b)
  {
    cout << a << ' ' << b;
  }
};

auto f = bind(foo(), _1, _2);
f("test", 1.2f); // will print "test 1.2"

タイプAとBはここでは固定されていないことに注意してください。fが実際に使用される場合にのみ、これら2つが推定されます。

于 2011-01-03T02:38:28.857 に答える
28

あなたが言ったように、バインドとラムダはまったく同じ目標を目指しているわけではありません。

たとえば、STL アルゴリズムを使用および構成する場合、ラムダは明らかに勝者です。

たとえば、スタック オーバーフローに関する非常に面白い回答を覚えています。誰かが 16 進数のマジック ナンバー (0xDEADBEEF、0xCAFEBABE、0xDEADDEAD など) のアイデアを尋ねたところ、彼が本物の C++ プログラマーなら、英単語のリストをダウンロードして、C++ の簡単なワンライナーを使用してください :)

#include <iterator>
#include <string>
#include <algorithm>
#include <iostream>
#include <fstream>
#include <boost/lambda/lambda.hpp>
#include <boost/lambda/bind.hpp>

int main()
{
    using namespace boost::lambda;
    std::ifstream ifs("wordsEn.txt");
    std::remove_copy_if(
        std::istream_iterator<std::string>(ifs),
        std::istream_iterator<std::string>(),
        std::ostream_iterator<std::string>(std::cout, "\n"),
        bind(&std::string::size, _1) != 8u
            ||
        bind(
            static_cast<std::string::size_type (std::string::*)(const char*, std::string::size_type) const>(
                &std::string::find_first_not_of
            ),
            _1,
            "abcdef",
            0u
        ) != std::string::npos
    );
}

このスニペットは、純粋な C++98 で、英単語ファイルを開き、各単語をスキャンして、'a'、'b'、'c'、'd'、'e'、または 'f' を含む長さ 8 の単語のみを出力します。文字。

次に、C++0X と lambda を有効にします。

#include <iterator>
#include <string>
#include <algorithm>
#include <iostream>
#include <fstream>

int main()
{
 std::ifstream ifs("wordsEn.txt");
 std::copy_if(
    std::istream_iterator<std::string>(ifs),
    std::istream_iterator<std::string>(),
    std::ostream_iterator<std::string>(std::cout, "\n"),
    [](const std::string& s)
    {
       return (s.size() == 8 && 
               s.find_first_not_of("abcdef") == std::string::npos);
    }
 );
}

これはまだ読むのが少し重いですが (主に istream_iterator ビジネスのため)、バインド バージョンよりもずっと簡単です :)

于 2009-12-19T01:20:12.503 に答える
18

C++ 0x lamdba 構文は、バインド構文よりも読みやすいです。2 ~ 3 レベル以上のバインドになると、コードはほとんど判読不能になり、保守が困難になります。より直感的なラムダ構文を好むでしょう。

于 2009-12-18T22:00:56.470 に答える
8

ラムダの利点の 1 つは、既存の関数の上に少し大きなロジックを追加する必要がある場合に、はるかに役立つことです。

バインドを使用すると、ロジックがこの 1 つの場所でのみ必要になる場合でも、新しい関数/メソッド/ファンクターを作成する必要があります。適切な名前を付ける必要がありますが、関連するロジックを分割する可能性があるため、コードがわかりにくくなる可能性があります。

ラムダを使用すると、ラムダ内に新しいロジックを追加できます (ただし、新しい呼び出し可能オブジェクトを作成することが理にかなっている場合は強制されません)。

于 2009-12-19T01:28:30.177 に答える
3

むしろ好みの問題だと思います。新しいテクノロジーをすぐに把握したり、関数型プログラミングに精通している人はおそらくラムダ構文を好むでしょうが、より保守的なプログラマーは、従来の C++ 構文と同等であるため、確実に bind を好むでしょう。

そのような決定は、おそらく多数決によって、コードで作業する人々と調整して行う必要があります。

ただし、ラムダ構文がはるかに強力でクリーンであるという事実は変わりません。

于 2009-12-18T22:15:31.207 に答える
2

C++0x ラムダは基本的にバインドを置き換えます。同じことを達成するために自明なラッパーラムダを再作成できないことをバインドできるものは何もありません。std::tr1::bind は、ラムダのサポートが広く普及すると、std::bind1st などと同じ道をたどります。なんらかの理由で、ほとんどのプログラマーはバインドについて理解するのに苦労しているため、これは良いことです。

于 2009-12-24T20:18:25.423 に答える