8

私は、メンバー関数を持つstd::vectorポインターPersonオブジェクトを持っていますstd::string getName() const。STL アルゴリズムを使用して、 「Chad」Personを返すベクトル内のすべてのオブジェクトをカウントしたいと考えています。getName()

ループを単純に反復する動作は次のようになります。

int num_chads = 0;
for(std::vector<Person *>::const_iterator it = vec.begin(); it != vec.end(); ++it)
{
    if((*it)->getName() == "Chad")
        ++num_chads;
}

これを作り直して、すべての STL アルゴリズムとファンクターなどを使用するようにします (より機能指向にします)。これは私がする必要があると私が思うことです:

const int num_chads = std::count_if(vec.begin(), vec.end(),
                                    std::bind1st(std::bind2nd(std::equal_to, mem_fun(Person::getName)), "Chad"));

おそらくおわかりのように、これは機能しません。まず、私が理解しているように、 bind1st/bind2nd オブジェクトは bind1st/binder2nd オブジェクトで動作するように特別に設計されているため、使用できませんstd::binary_functions。第二に、そしてもっと重要なことに、私は正しいテクニックを使っているとは思いません. 引数の1つを「チャド」にバインドしたいのですが、イテレータ引数を使用すると、実際には、バインドされたバージョンの を呼び出す前に、イテレータ値を文字列に変換したいだけですequals_to

Boost を使用してこれを行うことは可能だと思いますが、コア C++03 だけを使用して (つまり、C++0x ランバを使用しないで) 可能ですか?

編集: ユーザー定義の述語を使用しない (つまり、std ツールキットで提供されるツールを使用するだけの) 例を思いつく人はいますか?

編集: Matthieu の回答は STL アルゴリズムでファンクタを使用する方法についての教科書的な回答ですが、Cubbi の回答は私が探していたアプローチからのものでした (ただし、Mathieu は質問を編集してより具体的にする前に回答したため、お詫びします!)。

4

3 に答える 3

9

私はいつもラムダが比較的読みにくいことに気づきました。私は明示的な型を書くことを好みます:

struct Named
{
  Named(char const* ref): _ref(ref) {}
  bool operator()(Person* p) const { return p && p->getName() == _ref; }
  char const* _ref;
};

size_t const c = std::count_if(vec.begin(), vec.end(), Named("Chad"));

の定義Namedは「的外れ」ですが、適切に選択された名前は意図を伝え、実装の詳細を隠します。個人的には、これは良いことだと思います。なぜなら、実装の詳細に気を取られたり、コードのリバース エンジニアリングによって何が起こっているのかを理解しようとしたりしないからです (明らかなように)。

于 2011-03-16T13:24:24.650 に答える
5

実際のブースト コードはまだ投稿されていないため、C++98 とブースト:

ptrdiff_t num_chads = std::count_if(vec.begin(), vec.end(),
                      boost::bind(&Person::getName, _1) == "Chad");

試運転https://ideone.com/PaVJe

compose1純粋なC ++に関しては、STLには存在するがC ++ stdlibには存在しないアダプターなしでは不可能だと思います...

そしてここにあります(GCCのSTLの実装を使用)

ptrdiff_t num_chads = std::count_if(vec.begin(), vec.end(),
                     __gnu_cxx::compose1(
                         std::bind2nd(std::equal_to<std::string>(), "Chad"),
                         std::mem_fun(&Person::getName)));

テスト実行: https://ideone.com/EqBS5

編集:説明するために修正Person*

于 2011-03-16T14:29:02.720 に答える
1

を使用するboost::bindと、既存の標準バインディング メカニズムよりもかなり優れています。boost::bind完全に C++03 互換です。

于 2011-03-16T13:36:36.520 に答える