3

boost::bindプレースホルダーのいくつかの演算子をオーバーロードします。

便宜上、論理否定演算子と関係演算子および論理演算子、、、、、、、、をbindオーバーロードすることによって生成される関数オブジェクト。!==!=<<=>>=&&||

たとえば、これにより、_1 == desired_valueSTLアルゴリズムの述語として渡すことができます。

残念ながら、std::bindこれらの演算子をオーバーロードしていないようです:(

  1. 何故ですか?

  2. シミュレートするための適切な回避策は何_1 == desired_valueですかstd::bind

4

4 に答える 4

3

IIRC、Boost.Bindは、Boost.Bindが改良された元のBoost Lambdaライブラリが行ったため、プレースホルダーのこれらの演算子のみをオーバーロードします(Boost.BindはBoost.Phoenixのおかげで廃止されました)。std::bindのプレースホルダーは、への引数のプレースホルダーとして、まさにその目的のみを目的としていますstd::bind

回避策として、ポリモーフィックファンクターを使用します。

struct compare_equal{
  template<class LHS, class RHS>
  bool operator()(LHS&& lhs, RHS&& rhs){ // assume bool return
    return std::forward<LHS>(lhs) == std::forward<RHS>(rhs);
  }
};

// ...
auto bound = std::bind(compare_equal(), _1, desired_value);

Ideoneの実例。

于 2012-07-05T15:52:52.497 に答える
0

プレースホルダーのこれらの演算子は、いつでも自分でオーバーロードできます。次に例を示しoperator<ます。

struct less12
{
    template<typename T, typename U>
    bool operator()(const T& a, const U& b) const
    {
        return a < b;
    }
};

less12 operator<(decltype(_1), decltype(_2))
{
    return less12();
}


struct less21
{
    template<typename U, typename T>
    bool operator()(const U& b, const T& a) const
    {
        return a < b;
    }
};

less21 operator<(decltype(_2), decltype(_1))
{
    return less21();
}


template<typename T>
struct lessa1
{
    const T& a;

    template<typename U>
    bool operator()(const U& b) const
    {
        return a < b;
    }
};

template<typename T>
lessa1<T> operator<(const T& a, decltype(_1))
{
    lessa1<T> result = {a};
    return result;
}


template<typename U>
struct less1b
{
    const U& b;

    template<typename T>
    bool operator()(const T& a) const
    {
        return a < b;
    }
};

template<typename U>
less1b<U> operator<(decltype(_1), const U& b)
{
    less1b<U> result = {b};
    return result;
}

less12バインダー(カスタムvs std::less)およびラムダ構文と比較した使用例を次に示します。

template<typename Iterator>
void quicksort(Iterator begin, Iterator end)
{
    // ...
    auto m = std::partition(begin + 1, end, _1 < *begin);

    auto m = std::partition(begin + 1, end, std::bind(less12(), _1, *begin));

    auto m = std::partition(begin + 1, end, std::bind(std::less<typename std::iterator_traits<Iterator>::value_type>(), _1, *begin));

    auto m = std::partition(begin + 1, end, [begin](const typename std::iterator_traits<Iterator>::value_type& x) { return x < *begin; } );
    // ...
}

ここでN3421と多形ラムダを本当に楽しみにしています:)

于 2012-12-21T08:25:44.270 に答える
0

std :: bindはこれらの演算子をオーバーロードしていないようですか?何故ですか?

C ++ 11はラムダを追加したため、匿名ファンクターオブジェクトを生成するのに同じ便利さを提供します。

std ::bindで_1==desired_valueをシミュレートするための良い回避策は何ですか?

std :: bindは、動作のシミュレーションには使用されません。C ++ 11ラムダを使用して、質問への回答を実装します。

std::vector<int>::iterator it = std::find_if (myvector.begin(), myvector.end(), [](int i) -> bool { return i == desired_value; });

戻り型を導出できるかなり最近のコンパイラを使用している場合は、「->bool」構文は必要ないことに注意してください。

C ++ 11ラムダを使用したくない、または使用できない場合は、次のような非匿名ファンクターを作成できます。

bool IsDesiredValue (int i) {
    return (i == desired_value);
}
std::vector<int>::iterator i = std::find_if (myvector.begin(), myvector.end(), IsDesiredValue);

別の例として、C ++ 11ラムダを使用して匿名ファンクターを作成し、タイプの値でベクトルを並べ替えます。

std::sort(myVector.begin(), myVector.end(), [](const Foo& i, const Foo& j) -> bool { return i.myValue < j.myValue; });

代替の非ラムダバージョンは次のようになります。

struct myclass {
  bool operator() (const Foo& i, const Foo& j) { return (i.myValue < j.myValue); }
} myobject;
std::sort(myVector.begin(), myVector.end(), myobject);

そして、ブーストの演算子オーバーロードを使用して同じソートを行う方法は次のとおりです。

std::sort(myVector.begin(), myVector.end(), boost::bind(&MyClass::myValue, _1) < boost::bind(&MyClass::myValue, _2))
于 2014-02-21T17:27:12.470 に答える
-1

C ++ 11にはラムダがあるためだと思います。したがって、代わりにそのような演算子が必要になる理由がわかりません。

于 2012-07-05T15:43:12.403 に答える