std::bind 占位符的重载运算符
Overloaded operators for std::bind placeholders
boost::bind
为其占位符重载了几个运算符:
为方便起见,
bind
生成的函数对象重载逻辑非运算符!
以及关系和逻辑运算符==
、!=
、<
、<=
、>
、>=
、&&
、||
。
例如,这允许我将_1 == desired_value
作为谓词传递给 STL 算法。
不幸的是,std::bind
似乎并没有使这些运营商超载:(
-
为什么?
-
使用
std::bind
模拟_1 == desired_value
的好解决方法是什么?
IIRC,Boost.Bind只重载占位符的那些运算符,因为原始的Boost Lambda库,Boost.Bind是一个改进,做了(由于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上的活生生的例子。
您始终可以为占位符重载这些运算符,例如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
与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和多态λ在这里:)
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 lambda 来创建匿名函子以按类型值对向量进行排序的用法:
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))
这是因为 C++11 具有 lambda,因此我不明白为什么您需要这样的运算符。
- 为什么Mat类的两个对象可以在不重载运算符+的情况下添加
- 重载运算符new[]的行为取决于析构函数
- 为什么将值返回函数传递给重载=运算符对运算符函数有效,而对其他运算符无效
- 在 myVector 类中重载运算符 + 时出错
- 为什么常量词在重载运算符中不与 ostream 对象一起使用<<?
- 如何在 cpp 中重载运算符 +=?
- C++ 如何重载 [] 运算符并进行函数调用
- 重载运算符的范围是什么?它是否会影响作为类成员的集合的插入函数?
- 为什么我可以在不重载 "=" 运算符的情况下将一个对象分配给另一个对象?
- 重载运算符有地址吗?
- 如何迭代重载运算符 [] 的类?
- 重载运算符与添加问题
- 模板基类中的重载运算符
- 如何调用用于重载运算符"<<"的 friend 函数?
- 在 C++17 中的命名空间和子命名空间中重载运算符是不明确的
- 重载运算符<<采用谷歌 C++ 风格
- C++ 如何正确重载 + 运算符
- cout (<<) 重载运算符不打印减去的矩阵
- 如何在 c++ 中重载运算符 + 以便能够 whrite c_str = "smth" + c_str;
- 重载运算符*以获取对另一个类的实例的引用