为什么或何时在调用之前将可调用函数参数转换为右值?

时间:2018-07-06 10:14:48

标签: c++ move-semantics higher-order-functions

到目前为止,我已经考虑过传递和调用可调用对象

template <class Fct, class... Args> void f(Fct&& g, Args&&... args)
{
    g(std::forward<Args>(args)...);
}

是必经之路。现在,在this talk(第34分钟)和std::invoke示例实现中,我看到了上述片段的等效内容,该片段在调用可调用对象之前有条件地将其转换为右值引用

template <class Fct, class... Args> void f(Fct&& g, Args&&... args)
{
    std::forward<Fct>(g)(std::forward<Args>(args)...);
}

我假设此修改仅影响闭包,但我仍然不明白为什么第二个版本更可取:强制转换仅影响rvalue参数,调用时不应复制任何状态,对吗?我还检查了&&&上的std::function::operator()是否过载,以获取上述片段的替代库的提示,但这不是事实。

预先感谢您的提示和答案!

1 个答案:

答案 0 :(得分:6)

完美转发的目的是尽可能保留原始信息。

g(std::forward<Args>(args)...);将删除原始函数对象的右值/左值信息,g始终视为左值。

这将引起可观察的效果,例如:

struct foo {
    void operator()(int) & {
        std::cout << "& called\n";
    }

    void operator()(int) && {
        std::cout << "&& called\n";
    }
};

foo{}(1)将调用第二个operator()。如果您使用的第一种方法不带std::forward,则f(foo{}, 1)将调用第一个operator()