6

ファンクターと、または(C ++ 11の場合)名前空間からのテンプレートを使用して、ベクトルの要素の数をカウントするコードをref作成しましたbind。と名前空間を切り替えるためにを使用しています。Boostバージョン1.53を使用していて、コンパイルコマンドはです。gccバージョン4.7.2と4.6.3で試しましたが、両方で同じエラーが発生します。boost::std::#defineboost::std::g++ test.cpp -std=c++11

私は3つの質問があります:

  1. 例2で発生するエラーがわかりません。
  2. 名前空間を切り替えるだけで、このようなコードを移植可能にすることは可能ですか?
  3. 、、stdおよびboostのバージョンの違いを詳細に説明している優れたリファレンスはありますか?(私はこの質問を見ましたが、答えは言及していませんまたは)bindreffunctionreffunction

ありがとう!

PSこの例は私の問題を示しているだけです、私は知ってsize()いますstd::vector:-)

//#define USE_STD

#ifdef USE_STD
#include <functional>
using namespace std::placeholders;
namespace impl = std;
#else
#include <boost/version.hpp>
#include <boost/bind.hpp>
#include <boost/ref.hpp>
namespace impl = boost;
#endif

#include <iostream>
#include <algorithm>
#include <vector>

class Item {
    int id_;

public:
    Item(int id) : id_(id) {};
};

template <typename ITEM>
class Counter {
    int count_;

public:
    // typedef void result_type; // adding this fixes Example 3 when impl=boost
    Counter() : count_(0) {};
    void operator()(ITEM* item) {count_++;}
    int operator()() {return count_;}
};

//------------------------------------------------------------------------------
int main(int argc, char *argv[])
{
#ifndef USE_STD
    std::cout << "BOOST_LIB_VERSION=" << BOOST_LIB_VERSION << std::endl;
#endif

    // allocate
    typedef std::vector<Item*> ItemVec;
    ItemVec vec;
    for (int i = 0; i < 9; ++i) {vec.push_back(new Item(i));}

    // Example 1, works for BOTH
    Counter<Item> f1;
    f1 = std::for_each(vec.begin(), vec.end(), f1);
    std::cout << "f1()=" << f1() << std::endl;

    // Example 2, works with impl=std ONLY
    // COMPILE ERROR with impl=boost: "no match for call to ‘(boost::reference_wrapper<Counter<Item> >) (Item*&)’"
    Counter<Item> f2;
    std::for_each(vec.begin(), vec.end(), impl::ref(f2));
    std::cout << "f2()=" <<  f2() << std::endl;

    // Example 3, works with impl=std ONLY
    // COMPILE ERROR with impl=boost "no type named ‘result_type’ in ‘class Counter<Item>’"
    // this can fixed by adding the typedef described above
    Counter<Item> f3;
    std::for_each(vec.begin(), vec.end(), impl::bind(impl::ref(f3), _1));
    std::cout << "f3()=" << f3() << std::endl;

    // clean up
    for (ItemVec::iterator it = vec.begin(); it != vec.end(); ++it) {
        delete *it;
    }
    vec.clear();

    return 0;
}
4

2 に答える 2

4

例2は、とは異なり、引数を転送するメンバーboost::reference_wrapperがないため失敗します。そのため、呼び出されることが期待される関数やファンクターではなく、参照によって通常の引数を渡す場合にのみ役立ちます。operator()std::reference_wrapper

明示的なリターンタイプのないバージョンを使用する場合、Boost.Bindは特定のプロトコルに依存して、渡す関数またはファンクターの結果タイプを取得するため、例3は失敗します。関数へのポインターまたはメンバー関数へのポインターを渡すと、返されるバインダー・オブジェクトには、result_type上記のPTFまたはPTMFの戻りタイプにネストされたセットがあります。ファンクターを渡す場合は、ネストされたが必要result_typeです。
std::bind一方、result_typeファンクターにネストがない場合は、ネストがありません。

boost::bind私が言ったように、結果タイプをとの両方に明示的に提供できることに注意してくださいstd::bind

std::for_each(vec.begin(), vec.end(), impl::bind<void>(impl::ref(f3), _1));
//                                              ^^^^^^

これで例が修正され、コンパイルされます。

于 2013-02-25T19:37:57.217 に答える
2

std::ref1つの大きな利点があります:それは、含まれている参照に呼び出しを boost::ref転送する、varadic完全転送を提供します。operator()

boost::refかなりの数のオーバーロードが必要になるため、これを実際に行うことはできません。ただし、これを可能にするためにboost::bind(および他のいくつかのクラス)はすべて、の特別な処理を提供しboost::reference_wrapperます。

于 2013-02-25T19:39:15.163 に答える