4

関数オブジェクトの std::equal_to、std::greater などのファミリに一般的に相当する関数オブジェクトがブーストにありますか?

基本的に、 std::equal_to は次のようになります

struct generic_equal_to
{
    template <class T, class U>
    bool operator()(const T& t, const U& u) const
    {
        return t == u;
    }
};

std::plus などのジェネリック バージョンが、戻り値の型の問題によりトリッキーになる可能性があることがわかります (ただし、それdecltypeは解決できます)。ただし、 std::equal_to 関数オブジェクト自体がテンプレート引数を必要とする理由は考えられません。

これらのバージョンは、ブーストまたは STL のどこかに存在するのでしょうか? もちろん、それらを書くのは簡単ですが、私はライブラリ コードを複製することを非常に嫌います。

編集

ラムダや別の関数オブジェクト生成方法を使用する代わりに、なぜこれが必要なのかについてのコンテキストとして:

したがって、一般的なboost::fusionシーケンス比較関数を作成していました。

template <class T>
bool sequence_equal(const T& left, const T& right)
{
    return fusion::all(
        fusion::zip(left, right),
        fusion::fused<generic_equal_to>());
}

事実上、または関数オブジェクトを型でfusion::fused<generic_equal_to>指定できないという問題につながる部分に注意してください。1つの解決策はdecltypeかもしれないと思います:boost::lambdaboost::phoenix

fusion::fused<decltype(_1 == _2)>()

boost::lambdaしかし、それは非常に厄介なようで、実装方法や実装によってはうまくいかないかもしれませんboost::phoenix- 私にはよくわかりません.

fusion::make_fusedを使用してこの問題全体を回避できることは知っていますが、関数オブジェクトをインスタンス化する必要があります。私が考えた解決策は、テンプレートではないequal_to構造体です。私は mine と呼びましたgeneric_equal_to

私はそれが非常に些細な問題であることを知っていmake_fused(_1 == _2)ますfused<generic_equal_to>. generic_equal_toブーストやSTLのどこにも関数オブジェクトがないとは信じられなかったので、この質問です。

4

2 に答える 2

1

あなたが求めているほど直接的なものはないと思いますが、ユースケースをカバーするだけでなく、それを超えたユーティリティがあります. それらはBoost.LambdaBoost.Phoenix です(後者はラムダ ライブラリのより一般的な後継です)。

一般的な等価性のために Boost.Lambda を使用する例:

#include <boost/lambda/lambda.hpp>
#include <iomanip>
#include <iostream>

struct foo {};

bool operator==(foo, foo) { return true; }
bool operator==(foo, int) { return false; }

template <typename T, typename U, typename Func>
void f(const T& x, const U& y, Func func)
{
    std::cout << func(x, y) << std::endl;
}

int main()
{
    using namespace boost::lambda; // for placeholders
    std::cout << std::boolalpha;

    foo a, b;
    int i = 0;

    f(a, b, _1 == _2);
    f(a, i, _1 == _2);
}

フェニックスの場合も同様です。

#include <boost/phoenix.hpp>
#include <iomanip>
#include <iostream>

struct foo {};

bool operator==(foo, foo) { return true; }
bool operator==(foo, int) { return false; }

template <typename T, typename U, typename Func>
void f(const T& x, const U& y, Func func)
{
    std::cout << func(x, y) << std::endl;
}

int main()
{
    using namespace boost::phoenix::arg_names; // for placeholders
    std::cout << std::boolalpha;

    foo a, b;
    int i = 0;

    f(a, b, arg1 == arg2);
    f(a, i, arg1 == arg2);
}

これらのそれぞれは、明白な方法で (より一般的には、他の式に) 他の演算子をサポートするように拡張できます。ラムダが提供する機能よりも多くの機能が必要であることがわかった場合、両方を含めることはできないため、個人的には Phoenix を使用します。

于 2012-04-09T03:00:24.090 に答える