在将lambdas作为参数传递时,我应该避免转换为std :: function吗?

时间:2014-04-03 00:48:21

标签: c++ c++11 lambda

如果我有一个从输入对象生成钩子所需的函数,我应该尝试不转换为std::function吗?有了这两个选项,我应该选择哪个选项2是一个有意义的改进?

std::function<void()> CreateHook(std::function<void()> f)
{
    return []()
    {
        return Hook(f);
    };
}

// option 1:
void Hook(std::function<void()> f)
{
    // do something
}

// option 2:
<typename F>
void Hook(F f)
{
    // do something
}

2 个答案:

答案 0 :(得分:3)

在您的示例中,模板是没有意义的,因为它只是为T = std::function<void()>实例化了 - 模板重载是由{em>静态类型的f选择的,而不是运行时类型

答案 1 :(得分:3)

仅在需要时键入擦除。之一:

template<class F>
std::function<void()> CreateHook(F f) { return []() { return Hook(f); }; }

甚至在C ++ 1y中:

template<class F>
auto CreateHook(F f) { return [f=std::move(f)]() { return Hook(f); }; }

但第二个可能是矫枉过正(f=std::move(f)不是,auto是,因为我猜你只会将返回值存储在std::function中。

如果您的Hook功能简单而稳定:

template <typename F> void Hook(F f) {
  // do something
}

但如果它又大又复杂:

void Hook(std::function<void()> f) {
  // do something
}

因为它允许您从实现中拆分接口。

这种策略的缺点是一些编译器在消除不同函数中相同的代码时会导致二进制大小膨胀,这会导致编译时间膨胀。

但是如果在这两种情况下推迟类型擦除,则可以消除两个virtual函数调用,并允许编译器内联f体内传递的Hook。 / p>

但是,如果无法更改CreateHook的界面,并且仅Hooktemplate调用,则Hook std::function版本的内容毫无意义,因为它仅被调用无论如何,{{1}}。