【问题标题】:Passing a function object: Error传递函数对象:错误
【发布时间】:2010-10-16 04:29:09
【问题描述】:

下面这个传递函数对象的小程序有什么问题?

#include <iostream>
#include <functional>

void foo(const std::unary_function<const std::string&, void>& fct) {
  const std::string str = "test";
  fct(str); // error
}

class MyFct : public std::unary_function<const std::string&, void> {
public:
  void operator()(const std::string& str) const {
    std::cout << str << std::endl;
  }
};

int main(int argc, char** argv){
  MyFct f;
  foo(f);
  return 0;
}

我在第 6 行收到以下错误:

 no match for call to 
`(const std::unary_function<const std::string&, void>) (const std::string&)'

【问题讨论】:

    标签: c++ functional-programming unary-function


    【解决方案1】:

    一个常见的错误。 unary_functionbinary_function 只是添加 typedef 的两个结构体

    argument_type
    result_type
    

    分别

    first_argument_type
    second_argument_type
    result_type
    

    没有更多。它们是为了方便函数对象类型的创建者,所以他们不必自己做这些。但它们的行为不是多态的。你想要的是函数对象包装器。 boost::function 浮现在脑海中:

    void foo(boost::function<void(const std::string&)> const& fct) {
      const std::string str = "test";
      fct(str); // no error anymore
    }
    

    或者把它做成模板

    template<typename FunctionObject>
    void foo(FunctionObject const& fct) {
      const std::string str = "test";
      fct(str); // no error anymore
    }
    

    您可以按值获取它,然后从foo 返回副本,如果使用它将其应用于某个序列。这将允许函数对象更新其成员之间的一些状态变量。 for_each 就是一个这样做的例子。一般来说,无论如何,我会按价值接受它们,因为它们通常很小,复制它们可以提供更大的灵活性。所以我愿意

    template<typename FunctionObject>
    void foo(FunctionObject fct) {
      const std::string str = "test";
      fct(str); // no error anymore
    }
    

    然后您将能够获取 fct 的副本并将其保存在某处,fct 的 operator() 可以是非常量并更新一些成员(这是 operator() 的全部要点的一部分) .请记住,如果您通过 const 引用获取函数对象,通常不能复制它,因为用户可能已经传递了一个函数。然后复制它会尝试在本地声明一个函数而不是本地函数指针。但是,当传递函数时,按值接受将接受函数指针,可以安全地复制。

    【讨论】:

    • 感谢您的回答! Boost 方案和模板方案一样高效吗?
    • boost 解决方案效率不高,因为它必须对包装的函数对象进行间接调用(它为此创建了自己的 vtable)。但它的优点是您不需要模板。您可以使用该 boost.function 并将其存储在某处(例如作为类成员)。
    • 我认为它最接近您使用 unary_function 寻找的内容
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-05-09
    • 2020-03-08
    • 2023-04-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多