3

bind_range範囲に対してバインドできる独自の実装を試みています。次のようなクライアントコードを許可する必要があります。

void f(int x, int y)
{
    std::cout << x + y << ',';
}

std::vector<int> v1; // contains 1,2,3

void go()
{
    boost::function<void(int y)> f_bound = bind_range(f, v1, _1);
    f_bound(10); // prints 11,12,13,
}

上記のコードで、私のテンプレートは、に準拠し、その値型がの最初のパラメーターと互換性があることbind_rangeを検出します。次に、各値を呼び出して反復する関数オブジェクトを生成します。v1ForwardRangeConcept<>f()v1f()

上記は、呼び出し元のコードのfor-each構文の形式で実現できることは知っていますが、バインドされた関数を取得して後で使用したいと思います。

以上が私が達成したいことの本質です。C ++テンプレートメタプログラミングのコピーを読み、実装boost::bindを確認しましたが、解決策を開始できません。私はまた、このようなものがすでにBoostライブラリのどこかに存在しているというしつこい感じがします。

拡張機能:

複数の範囲をバインドします。 例えば:

std::vector<int> v10; // contains 10,20,30

void go_multiple()
{
    boost::function<void()> f_bound = bind_range(f, v10, v1);
    f_bound(); // prints 11,12,13,21,22,23,31,32,33,
}

返品タイプの取り扱い。 繰り返し呼び出しからの戻りタイプは必要ありませんが、誰かが各戻り値を格納または処理したいと思うかもしれません。これは、ある種のラムダタイプの構造でうまく実行できると確信しています。

4

3 に答える 3

3

私の知る限り、これはBoostには存在しません。これは、とで簡単に再現できるfor_eachためbindです。たとえば、次のようになります。

function<void()> bound = bind(
    for_each<vector<int>::iterator, function<void(int)> >, 
    v1.begin(), v1.end(), func
);`

かなり簡単です。bind_rangeバインディング情報(つまり、コンテナーとファンクター)を取得operator()し、コンテナーに関数を適用するコンストラクターを使用して、テンプレート化されたファンクターを作成する必要があります。

ただし、このようなファンクタを後で使用するために保存すると、bind_rangeオブジェクトが存在しなくなったコンテナを参照する可能性があるため、危険な場合が多いことに注意してください。

簡単な例:

template<typename Container, typename Function>
struct bind_range {
    bind_range(Container& target, Function func) 
        : container(target), function(func) { }

    void operator()() {
        std::for_each(container.begin(), container.end(), function);
    }

    Function function;
    Container& container;
};
于 2011-03-31T12:20:12.070 に答える
0

私はこれに少し取り組みました、そしてこれが私が思いついたものです。動作しますが、範囲が最初のパラメーターにバインドされている単項関数と2進関数のテンプレートしかないため、不完全です。誰かがこれをさらに進めてより一般的にした場合は、ここに投稿してください。

#include <boost/bind.hpp>
#include <boost/range.hpp>
#include <boost/range/value_type.hpp>
#include <boost/type_traits/function_traits.hpp>
#include <boost/foreach.hpp>

template <class Range>
struct GetRangeValue
{
    typedef typename boost::range_value<Range>::type Value;
};

template <class Function, class Range>
struct BindForEachBase
{
    BindForEachBase(Function *f, Range &r) : function(f), range(r) { }
    Function *const function;
    Range &range;
};

template <class Function, class Range>
struct BindForEach1
    : BindForEachBase<Function, Range>
{
    BindForEach1(Function *f, Range &r) 
        : BindForEachBase(f, r) 
    { }
    void operator()() 
    { 
        BOOST_FOREACH(GetRangeValue<Range>::Value v, range) (*function)(v); 
    }
};

template <class Function, class Range>
BindForEach1<Function, Range> 
bindForEach(Function *f, Range &r)
{
    return BindForEach1<Function, Range>(f, r);
}

template <class Function, class Range, class A1>
struct BindForEach2
    : BindForEachBase<Function, Range>
{
    BindForEach2(Function *f, Range &r) 
        : BindForEachBase(f, r) 
    { }
    void operator()(A1 a1)
    {
        boost::function1<void, GetRangeValue<Range>::Value> f(boost::bind(*this->function, _1, a1));
        bindForEach(&f, range)();
    }
};

template <class Function, class Range, class Placeholder1>
typename boost::enable_if
<
    boost::is_placeholder<Placeholder1>, 
    BindForEach2<Function, Range, typename boost::function_traits<Function>::arg2_type> 
>::type 
bindForEach(Function *f, Range &r, Placeholder1 p1)
{
    return BindForEach2<Function, Range, boost::function_traits<Function>::arg2_type >(f, r);
}

void f(int x, int y)
{
    std::cout << x + y << ',';
}

#include <boost/assign/std/vector.hpp>
#include <vector>
using namespace boost::assign;

void go()
{
    std::vector<int> v1; 
    v1 += 1,2,3;
    boost::function<void(int y)> f_bound = bindForEach(f, v1, _1);
    f_bound(10); // prints 11,12,13,
}
于 2011-04-01T13:11:04.937 に答える
0

何が問題なのかわかりません。これは、コードを呼び出す際のfor_each構文によって実現できるとおっしゃいました。そうですね。それなら、そのfor_eachコンストラクトをbind_rangeファンクター自体に入れてみませんか?つまり、bind_rangeはoperator()を使用した構造体テンプレートになります。この演算子では、for_eachを実行する必要があります。私は何かが足りないのですか?

于 2011-03-31T09:25:08.357 に答える