【问题标题】:How to write a function that takes a functor as an argument如何编写一个以函子为参数的函数
【发布时间】:2011-10-16 21:36:43
【问题描述】:

基本上我想这样做: Can I use a lambda function or std::function object in place of a function pointer?

显然,对于需要函数指针的函数来说,目前这是不可能的。但是,它适用于需要仿函数的函数(我之前使用 stl 的 sort() 函数做过)

但是,我不知道如何编写一个将函子作为参数的函数!

有人吗?

【问题讨论】:

  • “显然这是不可能的”——实际上,它可能的。但是,只有无状态的 lambda 可以转换为函数指针。

标签: c++ visual-studio-2010


【解决方案1】:

只要写函数取任意类型即可:

template <typename Func>
void foo(Func fun)
{
    fun(...);
}

这将同样适用于函数指针、函子和 lambda。

void f() {}

struct G
{
    void operator()() {}
};

foo(&f);           // function pointer
foo(G());          // functor
foo([]() { ... }); // lambda

【讨论】:

  • 这留下了问题。 another answer 中提到的示例包括一个带有局部变量的函子。如果我将add42() 传递为add42() 而不是add42,那么add42 在评估时会得到准确的42 吗?
  • 这不是一个类型安全的解决方案,如果你想传入一个函数,使用 std::function 就像下面的 fredoverflow 的答案。
  • @sprite (该评论是旧的但是)请注意 std::function 会产生运行时开销;此外,“非类型安全”是什么意思?如果无法调用提供的函数(但在实现中的实际函数调用fun(...) 而不是foo(...) 行),此函数将引发编译错误。
【解决方案2】:

我不知道如何编写一个以函子作为参数的函数!

由于还没有人发布std::function 解决方案:

#include <functional>
#include <iostream>

void foo(std::function<int(int)> f)
{
    for (int i = 0; i < 10; ++i)
    {
        std::cout << f(i) << ' ';
    }
    std::cout << '\n';
}

int main()
{
    foo( [](int x) { return x*x; } );
}

您可以在 C++11 之前的编译器中使用 boost::function

【讨论】:

  • @Kerrek:为什么这是一件好事?这会导致无意义的类型擦除,即不必要的运行时性能损失。我认为 std::function&lt;&gt; 只有在需要非本地持久性时才应该使用。
  • @ildjarn:也许吧。如果不了解实际的函数体和应用程序,就不可能争论利弊。您说得对,模板化版本具有一定的优势,但了解非模板化方法也很好。
  • @Kerrek :我可以同意。 :-]
【解决方案3】:

它必须是一个模板,例如:

template<class F>
void foo( const F& f )
{
    f(x,y);
}

【讨论】:

  • 函子通常按值传递。
  • @FredOverlow:我会说这是个人喜好。我个人通常倾向于使用 pass by const-ref。
  • @PlasmaHH :除了个人喜好之外,还有更多内容,关键是您的方式需要 const operator() 定义,而按值传递则不需要。例如,std::for_each 无法按照您的方式工作。
  • @PlasmaHH :但是如果您要求他们的operator() 为常量,他们如何保持状态?
  • 虽然这是一个技术上正确的回答,但它并没有回答问题的精神——如果你特别想支持有状态函子,你为什么要强迫函子作者绕过 const-correctness 规则,当按值传递时(就像标准库所做的那样,它开创了 IMO 的先例)会让她的工作轻松吗?
猜你喜欢
  • 1970-01-01
  • 2016-02-07
  • 2012-01-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-08-16
  • 1970-01-01
  • 2011-05-30
相关资源
最近更新 更多