使用 std::function 或转发引用作为高阶函数的通用可调用对象输入参数?

Fde*_*deF 4 c++ perfect-forwarding c++11 std-function

我想知道编写一个高阶函数的主要区别、优缺点,作为输入参数,astd::function转发引用,例如template<typename F> void hof(F&& fun);. 显然,前者比后者更严格,因为它指定了输入可调用对象必须符合的函数类型

Vit*_*meo 5

std::function通常具有显着的运行时开销。通过template参数传递通用可调用对象避免了std::function间接成本,并允许编译器积极优化

我在本文末尾为 lambda 递归编写了一些简单的基准测试(Y-combinator vs std::function。总是比非多态 Y 组合器实现生成至少 3.5 倍的程序集。这是一个体面的例子,展示了如何比参数更昂贵。std::functionstd::functiontemplate

我建议在gcc.godbolt.org上玩一下,看看这两种技术之间的装配差异。


这是我刚刚想出的一个例子:

#if defined(STDFN)
void pass_by_stdfn(std::function<void()> f)
{
    f();
}
#else
template <typename TF>
void pass_by_template(TF&& f)
{
    f();
}
#endif

volatile int state = 0;

int main()
{
#if defined(STDFN)
   pass_by_stdfn([i = 10]{ state = i; });
#else
   pass_by_template([i = 10]{ state = i; });  
#endif
}
Run Code Online (Sandbox Code Playgroud)

使用STDFN not defined,生成的程序集是:

main:
        mov     DWORD PTR state[rip], 10
        xor     eax, eax
        ret
state:
        .zero   4
Run Code Online (Sandbox Code Playgroud)

使用STDFN defined,生成的程序集长度为 48 行。