完美转发函子

Perfect forwarding a functor

本文关键字:转发 完美      更新时间:2023-10-16

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

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-qualified operator(),第一个版本可能会做错事。考虑:

struct C {
    void operator()() && { std::cout << "rvaln"; }
    void operator()() const & { std::cout << "lvaln"; }
};
callMe(C{});

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

因此,正确的解决方案是第二个 - 这也是forward func

<小时 />

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

当您要将对象(可能是右值)传递给其他函数并且您不确定它是右值还是左值的情况下,完美转发很有用。在这种情况下,您只需使用 func ,因此转发它没有任何好处或坏处。

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

此外,它实际上仅在有可能为您转发的内容调用复制或移动构造函数时才有用。在许多情况下,const T&会做得很好。

编辑:

正如贝瑞指出的那样,func是否具有参考资格operator()确实很重要。我从未见过或使用过 ref 限定的方法(据我所知。这是非常罕见的。更多在巴里的回答中。

它也会读到这个:什么是"*这个的右值参考"?

struct C {
    void operator()() && { std::cout << "rvaln"; }
    void operator()() const & { std::cout << "lvaln"; }
};
callMe(C{});