这些不是函数,而是类(实际上是结构体,但这并不重要)。当你定义自己的二元函数以用于STL算法时,你从这些类派生它们,以便自动获取所有typedef。
例如:
struct SomeFancyUnaryFunction: public std::unary_function<Arg_t, Result_t>
{
Result_t operator ()(Arg_t const &)
{
...
}
};
现在你无需手动提供argument_type
,result_type
等typedef。这些结构体就像iterator
结构体一样方便我们重复使用算法所需的typedef。
C++11更新:
从C++11开始,新的std::bind
实际上不需要任何typedef,因此它们在某种程度上已过时。
typedef
,以允许使用函数适配器从一元和二元函数对象组合高阶函数。例如,这允许在需要一元函数的位置使用二元函数对象,将其中一个参数绑定到文字值:std::find_if( begin, end, std::bind1st(greater<int>(),42) );
std::bind1st
依赖于传递给它的函数对象来提供这些类型。
据我所知,新的 std::bind
不需要它们,因此在新代码中,您可以使用 std::bind
并且不需要使用它们。
sgi STL文档中有一个关于函数对象的解释。简而言之,unary_function和binary_function用于使函数对象适配。这使它们可以与函数对象适配器(如unary_negate)一起使用。
std::unary_function和std::binary_function是创建可适应函数对象的基础结构体。 "可适应"一词意味着它们提供了必要的typedef,以便与标准函数适配器(如std::not1、std::not2、std::bind1st、std::bind2nd)一起使用。
每当您需要将自定义函数对象与标准函数适配器一起使用时,都可以使用它们。
让我们考虑一些示例(我知道它们是人工的,但从另一方面来说,我希望它们相当描述性)。
示例1。
假设您想打印一个向量中所有长度不小于特定阈值的字符串并将它们打印到std::cout中。
可以使用下一个函数对象:
class LengthThreshold
{
public:
LengthThreshold(std::size_t threshold) : threshold(threshold) {}
bool operator()(const std::string& instance) const
{
return (instance.size() < threshold);
}
private:
const std::size_t threshold;
};
现在的任务非常简单,可以通过std::remove_copy_if算法执行:
// std::size_t threshold is defined somewhere
std::remove_copy_if(some_strings.begin(), some_strings.end(),
std::ostream_iterator<std::string>(std::cout, "\n"),
LengthThreshold(threshold)
);
// std::size_t threshold is defined somewhere
std::remove_copy_if(some_strings.begin(), some_strings.end(),
std::ostream_iterator<std::string>(std::cout, "\n"),
std::not1(LengthThreshold(threshold))
);
class LengthThreshold : public std::unary_function<std::string, bool>
{
// Function object's body remains the same
}
现在我们的第一个例子完美运行。
例子2。
让我们改变我们之前的例子。假设我们不想在函数对象内部存储一个阈值。在这种情况下,我们可以将函数对象从一元谓词更改为二元谓词:
class LengthThreshold : public std::binary_function<std::string, std::size_t, bool>
{
public:
bool operator()(const std::string& lhs, std::size_t threshold) const
{
return lhs.size() < threshold;
}
};
并使用 std::bind2nd 函数适配器:
// std::size_t threshold is defined somewhere
std::remove_copy_if(some_strings.begin(), some_strings.end(),
std::ostream_iterator<std::string>(std::cout, "\n"),
std::bind2nd(LengthThreshold(), threshold)
);
上述所有示例故意只使用了C++03。
原因是C++11开始,std::unary_function和std::binary_function被废弃,C++17中彻底删除。
这是由于更加通用和灵活的函数出现,例如std::bind,使得继承自std::unary_function和std::binary_function变得多余。
operator(Arg_t const &)
应该替换为operator()(Arg_t const &)
,或者我有什么遗漏了吗? - Luca Martini