代码之家  ›  专栏  ›  技术社区  ›  penguru

我们需要一元函数和二元函数做什么?

  •  12
  • penguru  · 技术社区  · 14 年前

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

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

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

    4 回复  |  直到 14 年前
        1
  •  13
  •   Armen Tsirunyan    8 年前

    这些不是函数,而是类(实际上是结构,但并不重要)。当您定义自己的二进制函数用于STL算法时,您将从这些类派生它们,以便自动获取所有typedef。

    例如。

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

    现在不需要手动为 argument_type , result_type 等等,这些结构,就像 iterator 结构的存在只是为了我们的方便,以便重用算法所需的typedef。

    C++ 11的更新:

    作为C++ 11,新的 std::bind 实际上不需要任何typedef,因此在某种程度上已经过时了。

        2
  •  7
  •   sbi    8 年前

    基本上,他们提供了 typedef 允许使用函数适配器从一元和二元函数对象组合高阶函数所必需的。例如,这允许在需要一元的情况下使用二元函数,将其中一个参数绑定到文字值:

    std::find_if( begin, end, std::bind1st(greater<int>(),42) );
    

    std::bind1st 依赖传递给它的函数来提供这些类型。

    新的阿法克 std::bind 不需要,所以在新代码中似乎可以使用 STD::绑定 把他们赶走。

        3
  •  6
  •   Daniel Lidström    14 年前

    有一个关于SGI STL文档的解释 Function Objects . 总之,一元函数和二元函数用于生成函数 适应性强 . 这允许它们与函数对象适配器一起使用,例如 unary_negate

        4
  •  3
  •   Edgar Rokjān    8 年前

    他们是什么?

    std::unary_function std::binary_function 是用于创建适应性函数对象的基本结构。这个词 适应性强 意味着它们提供必要的typedef,以便与标准函数适配器(如 STD::NOT1 , STD::NOT2 , STD::宾得 , STD::BND2

    当我需要使用它们的时候?

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

    你有例子吗?

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

    例1。

    假设你想全部打印 在一个 矢量 其长度不小于特定阈值,并将其打印到 STD::

    可以使用下一个函数对象:

    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::删除 算法:

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

    实际上,上面的代码不会编译,因为 长度阈值 不可适应并且没有必需的typedef STD::NOT1

    为了使它具有适应性,我们需要继承自 STD::Unayle函数 :

    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::BND2 功能适配器:

    // 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::Unayle函数 性传播疾病: 自以来已弃用 C++ 11 完全从 C++ 17

    它是随着更广泛和更灵活的函数的出现而出现的,比如 std::bind 继承自 STD::Unayle函数 性传播疾病: 多余的。