繁体   English   中英

我们需要unary_function和binary_function做什么?

[英]What do we need unary_function and binary_function for?

我阅读了有关二进制和一元函数的教程。 我理解它们的结构,但我无法想象在哪种情况下我需要这些功能。 你能给出一个使用它们的例子吗?

http://www.cplusplus.com/reference/std/functional/unary_function/

http://www.cplusplus.com/reference/std/functional/binary_function/

这些不是函数,这些是类(结构,实际上,但无关紧要)。 当您定义自己的二进制函数以与STL算法一起使用时,可以从这些类派生它们以自动获取所有typedef。

例如

struct SomeFancyUnaryFunction: public std::unary_function<Arg_t, Result_t>
{
   Result_t operator ()(Arg_t const &)
   {
      ...
   }
};

现在你不需要为argument_typeresult_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::bind1st函数来提供这些类型。

AFAIK新的std::bind不需要它们,所以在新代码中你可以使用std::bind并取消它们。

有关函数对象的sgi STL文档的解释。 总之,unary_function和binary_function用于使functor 适应 这允许它们与函数对象适配器一起使用,例如unary_negate

这些是什么?

std :: unary_functionstd :: binary_function是用于创建自适应函数对象的基础结构。 适应这个词的意思,它们用于与比如std :: NOT1, 性病:: NOT2, 性病:: bind1st, 性病:: bind2nd标准函数适配器结合使用提供必要的typedef。

什么时候需要使用它们?

每次需要将自定义函数对象与标准函数适配器一起使用时,可以使用它们。

你有一个例子吗?

让我们考虑一些例子(我知道,它们是人为的。从另一方面来说,我希望它们具有相当的描述性)。

例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 :: not1函数适配器:

// 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))
);

实际上,上面的代码将无法编译,因为我们的LengthThreshold不具有适应性,并且没有std :: not1所必需的typedef。

为了使其适应性,我们需要从std :: unary_function继承:

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 ++ 11及更高版本呢?

以上所有示例都故意仅使用C ++ 03

原因是std :: unary_functionstd :: binary_functionC ++ 11开始被弃用,并且完全从C ++中删除17

它发生在更广泛和灵活的函数的出现,如std :: bind ,它继承了std :: unary_functionstd :: binary_function是多余的。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM