当使用模板支持仿函数作为参数时,我应该使用什么限定符?

When using templates to support functor as arguments, what qualifier should I use?

考虑这段代码:

template<class F>
void foo1(F f) { f(); }

template<class F>
void foo2(F const& f) { f(); }

template<class F>
void foo3(F&& f) { f(); }

我应该使用 foo 的哪个版本? foo1 是我看到最多的 "in the wild" 但我担心它可能会引入我不想要的副本。我有一个自定义仿函数,复制起来有点麻烦,所以我想避免这种情况。目前我倾向于 foo3(因为 foo2 不允许变异函子)但我不确定其含义。

我的目标是 C++11。

我实际上更喜欢 foo3 而不是 foo1(虽然正文应该是 std::forward<F>(f)();

foo3 将导致类型 F 被推导为允许您完美转发由于 reference collapsing 引起的参数的类型。这很有用,因为默认情况下您不会复制任何内容,并且如果您决定要将仿函数转发给确实需要它的副本的对象,则可以维护值类别(左值与右值)。

一般来说,如果您的函数要存储它自己的仿函数副本,第一种形式 (foo1) 没问题,但第三种形式 (foo3) 更适合转发 (使用)参数。

我还推荐 Scott Meyers 关于 universal references, as well as this related Stack Overflow question 的精彩 post。