【问题标题】:What is the benefit of inheriting from std::binary_function (or std::unary function)?从 std::binary_function (或 std::unary 函数)继承有什么好处?
【发布时间】:2023-04-01 17:01:01
【问题描述】:

从 std::binary_function(或 std::unary_function)继承有什么好处?

例如我有这样的代码:

class Person
{
 public:
    Person();
    Person(int a, std::string n);
    Person(const Person& src);

    int age;
    std::string name;
 };

 Person::Person()
           : age(0)
             , name("")
               {};

 Person::Person(int a, std::string n)
 : age(a)
 , name(n)
 {};

 Person::Person(const Person& src)
 {
   age = src.age;
   name = src.name;
 };

 struct PersonPrint : public std::unary_function<Person, void>{
   void operator() (Person p){
     std::cout << " Person age: " << p.age 
               << " name: " << p.name << std::endl;
   }
 };

 struct PersonGreater : public std::binary_function<Person, Person, bool>{
   bool operator()(const Person& p1, const Person p2){
     if (p1.age > p2.age) return true;
     if (p1.name.compare(p2.name) > 0) return true;
     return false;
   }
 };

 int main(int count, char** args)
 {
   std::vector<Person> personVec;
   Person p1(10, "Person1");
   Person p2(12, "Person2");
   Person p3(12, "Person3");

   personVec.push_back(p1);
   personVec.push_back(p2);
   personVec.push_back(p3);

   std::cout << "before sort: " << std::endl;
   std::for_each(personVec.begin(), personVec.end(), PersonPrint());
   std::sort(personVec.begin(), personVec.end(), PersonGreater());
   std::cout << "after: " << std::endl;
   std::for_each(personVec.begin(), personVec.end(), PersonPrint());
 }

但是我也可以在没有继承形式std::unary_function/std::binary_function的情况下编写这段代码?

 struct PersonPrint {
     void operator() (Person p) {
         std::cout << " Person age: " << p.age << " name: " << p.name << std::endl; 
     } 
 }; 

 struct PersonGreater {
     bool operator()(const Person& p1, const Person p2) {
         if (p1.age > p2.age) return true; 
         if (p1.name.compare(p2.name) > 0) return true; 
         return false; 
     } 
 };

更新

std::binary_function 和 std::unary_function 自 C++11 起已弃用,请参阅@AlexandreC 的评论。

【问题讨论】:

  • 它们在 C++11 中已被弃用(当然,在提出问题时还没有 C++11)。
  • @AlexandreC。我们应该改用什么?在 c++ 编码标准中,andrei 提到它们对于构造与 stl 算法一起使用的函子至关重要
  • @kirill_igum:现在decltypeautostd::result_of 可用,您不需要继承任何东西。此外,bind1stbind2nd 已被弃用,取而代之的是 bind
  • @AlexandreC。所以也不需要创建仿函数而不是函数吗?早些时候,函子的原因是可以从 binary_function 中继承。
  • @kirill_igum:仿函数可以存储状态,而裸函数不能。

标签: c++ stl


【解决方案1】:

从 [unary|binary]_function 继承只是在你的类中给你一个额外的 typedef:

对于一元函数

argument_type
result_type

对于二进制函数

first_argument_type
second_argument_type
result_type 

您传递给 [unary|binary]_function 的那些类型是什么。 在你的情况下,没有任何好处。

如果您打算将您的 Functor 与其他 std Functor 修饰符(例如 not1、bind1st)一起使用,您必须从 [unart|binart]_function 继承。

如果您要为自己的目的存储此模板信息,最好使用现成的解决方案。

【讨论】:

  • 您应该注意这些类型定义是由 stl 函数库使用的,例如否定符 not1 和 not2。
【解决方案2】:

除了 typedef(已经提到过)之外,还有可读性方面。当我看到struct Foo {... 时,我首先想到的是“Foo 是一种类型”。但是有了struct Foo : public unary_function&lt;...,我已经知道 Foo 是一个函子。对于程序员(与编译器不同),类型和函子是截然不同的。

【讨论】:

  • 严格来说,Foo 绝不是函子。它要么是一个类型,要么是一个仿函数type。函子本身就是函子类型的实例化。
【解决方案3】:

就像 Mykola 解释的那样,他们只是添加了 typedef。想象一下,对于您的PersonGreater,您想将第一个参数固定给某个人。 binder1st 需要将第一个参数存储在某处,因此它需要第一个参数的类型。 binary_function 将其作为 typedef 提供:

// get a function object that compares person1 against 
// another person
std::bind1st(PersonGreater(), person1)

现在,返回的binder1st 对象知道它需要存储的参数类型是Person 类型。

一些函数对象否定另一个函数对象的结果。这里我们也需要参数的类型:

template <class Predicate>
class unary_negate
    : public unary_function<typename Predicate::argument_type,bool> {
    Predicate pred;
public:
    explicit unary_negate(const Predicate& pred):pred(pred) { }
    bool operator()(const typename Predicate::argument_type& x) const {
        return !pred(x);
    }
};

这也可以使用模板化的operator(),但标准将其定义为使用argument_type 类型作为参数。否定器本身是从 unary_function 派生的,无论如何都需要提供第一个参数类型。

有时,人们尝试使用[unary,binary]_function 来存储函数对象/指针。但是,它们不能用于此目的。 boost::function 完成了这项工作,并将在下一个标准中采用 std::function

【讨论】:

  • @litb:关于 bind1st 的要点。从未将我的对象函子与 bind1st 一起使用。
【解决方案4】:

这是编译器强制执行的一种强大的文档形式。

通过继承,您承诺您将实现 binary_function 接口,编译器将支持您。然后,客户可以相信您的类可以在任何需要 binary_function 的地方使用。

【讨论】:

    猜你喜欢
    • 2015-04-02
    • 2014-01-31
    • 2015-06-13
    • 1970-01-01
    • 1970-01-01
    • 2014-12-06
    • 1970-01-01
    • 2015-10-27
    • 1970-01-01
    相关资源
    最近更新 更多