3

boost::bind为其占位符重载了几个运算符:

为方便起见,通过bind重载逻辑非运算符!以及关系和逻辑运算符==, !=, <, <=, >, >=, &&,生成的函数对象||

例如,这允许我_1 == desired_value作为谓词传递给 STL 算法。

不幸的是,std::bind似乎并没有使这些运算符重载:(

  1. 这是为什么?

  2. 什么是模拟的好解决_1 == desired_value方法std::bind

4

4 回答 4

3

IIRC,Boost.Bind 仅重载了占位符的那些运算符,因为 Boost.Bind 是改进的原始 Boost Lambda 库确实(由于 Boost.Phoenix,Boost.Bind 已过时,顺便说一句)。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;
}

这是一个使用示例,与活页夹(自定义less12vs std::less)和 lambda 语法相比:

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和多态 lambdas :)

于 2012-12-21T08:25:44.270 回答
0

std::bind 似乎没有重载这些运算符?这是为什么?

因为 C++11 添加了 lambda,它们提供了相同的(如果不是更好的话)方便来生成匿名函子对象。

用 std::bind 模拟 _1 == desired_value 的好方法是什么?

std::bind 不用于模拟行为。使用 C++11 lambda 实现您问题的答案:

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

请注意,如果您使用的是可以派生返回类型的相当新的编译器,则不需要“-> bool”语法。

如果您不想或不能使用 C++11 lambda,那么您可以像这样创建一个非匿名仿函数:

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

再举一个例子,这里是使用 C++11 lambdas 来创建匿名函子,以按类型的值对向量进行排序:

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

另一种非 lambda 版本是:

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

以下是使用 boost 的运算符重载进行相同排序的方法:

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 有 lambda,因此我不明白为什么你需要这样的运算符。

于 2012-07-05T15:43:12.403 回答