完美转发一个仿函数

Perfect forwarding a functor

我想知道使用完美转发函子的正确方法是什么?这是两个代码片段。哪个最好,如果都不是,最好的形式是什么?

template<typename T, typename... Args>
void callMe(T&& func, Args&&... args) {
    func(std::forward<Args>(args)...);
}

template<typename T, typename... Args>
void callMe(T&& func, Args&&... args) {
    std::forward<T>(func)(std::forward<Args>(args)...);
}

编辑:

它会影响过载解析吗?如果 funcoperator()&&const & 的 ref-qualifier,我应该做后一个版本吗?我应该关心我调用哪个重载吗?

谢谢!

完美转发在您要传递一个对象(可能是右值)给其他函数的情况下很有用,而您不确定它是否是右值或左值。在这种情况下,你只是使用 func,所以转发它没有好处或坏处。

请记住,std::forward 是一个条件 std::move,它只是对右值引用的转换。

此外,只有当您转发的内容有可能调用复制或移动构造函数时,它才真正有用。在许多情况下,const T& 就可以了。

编辑:

正如 berry 指出的那样, 如果 func 有 ref-qualified operator() 就很重要。我从未见过或使用过 ref 限定方法(据我所知。这种情况极为罕见。)更多信息请参见 Barry's answer。

它也会这样读:What is "rvalue reference for *this"?

struct C {
    void operator()() && { std::cout << "rval\n"; }
    void operator()() const & { std::cout << "lval\n"; }
};

callMe(C{});

由于 ref-qualified operator() 存在,第一个版本可能会做错事。考虑:

struct C {
    void operator()() && { std::cout << "rval\n"; }
    void operator()() const & { std::cout << "lval\n"; }
};

callMe(C{});

我给你一个右值 - 并希望看到 "rval" - 但在第一个版本中,你总是将函数对象视为左值 - 所以我真的看到 "lval".

所以正确的解决方案是第二种 - forwards func 也是如此。


在实践中,我不知道引用限定成员函数实际发生的频率,所以前者可能没问题。