我想知道使用完美转发仿函数的正确方法是什么?这是两个代码段。哪一个是最好的,如果不是,哪个是最好的形式?
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)...);
}
编辑:
它会影响重载分辨率吗?如果func
的{{1}}具有operator()
或&&
的参考限定符,我应该执行后一版本吗?我应该关注我调用的重载吗?
谢谢!
答案 0 :(得分:5)
如果您要将对象(可能是右值)传递给其他某个功能,并且您不确定它是否属于右值或左值。在这种情况下,您只需使用 func
,因此转发它不会有任何好处或伤害。
请记住,std::forward
是条件std::move
,它只是对r值引用的强制转换。
此外,如果可能会为您转发的内容调用复制或移动构造函数,那么它才真正有用。在许多情况下,const T&
会做得很好。
修改强>
正如莓果指出的那样,如果func
具有参考资格operator()
,那么确实无关紧要。我从未见过或使用过合格的方法(据我所知。这非常罕见。)Barry的回答更多。
它也会读到这个:What is "rvalue reference for *this"?
struct C {
void operator()() && { std::cout << "rval\n"; }
void operator()() const & { std::cout << "lval\n"; }
};
callMe(C{});
答案 1 :(得分:5)
由于存在ref-qualified operator()
,因此第一个版本可能做错了。考虑:
struct C {
void operator()() && { std::cout << "rval\n"; }
void operator()() const & { std::cout << "lval\n"; }
};
callMe(C{});
我给你一个右值 - 并期望看到"rval"
- 但在第一个版本中,你总是像左值一样对待函数对象 - 所以我真的看到了{{ 1}}。
所以正确的解决方案将是第二个 - "lval"
s forward
也是如此。
在实践中,我不知道参与合格的成员函数实际发生的频率,所以前者很可能。