C++:std::invoke 需要完美转发吗?
C++: does std::invoke need perfect forwarding?
片段
template <typename CallableType, typename... Args>
auto invokeTest(CallableType&& fn, Args&&... args)
{
return std::invoke(fn, std::forward<Args>(args)...);
}
这里需要std::forward<Args>
吗?
还是写
就够了
template <typename CallableType, typename... Args>
auto invokeTest(CallableType&& fn, Args&&... args)
{
return std::invoke(fn, args...);
}
有什么区别?
好吧,我会说是,但这要视情况而定。
在这种情况下您不需要转发:
void bar(int);
int main() {
int i = 0;
invokeTest(bar, i);
}
但是,您需要转发这种情况:
void foo(std::unique_ptr<int>);
int main() {
auto p = std::make_unique<int>();
invokeTest(foo, p); // Won't work, cannot copy unique_ptr
}
写std::invoke(fn, args...)
时,args...
都是左值,此时我建议用Args const&...
取参数更清楚。
如果你转发,那么你移动了参数中右值的对象:
template <typename CallableType, typename... Args>
auto invokeTest(CallableType&& fn, Args&&... args)
{
return std::invoke(fn, std::forward<Args>(args)...); // all forward value caterories
}
invokeTest(foo, std::move(p)); // works.
如果您使用 Args&&...
,请使用转发。
片段
template <typename CallableType, typename... Args>
auto invokeTest(CallableType&& fn, Args&&... args)
{
return std::invoke(fn, std::forward<Args>(args)...);
}
这里需要std::forward<Args>
吗?
还是写
template <typename CallableType, typename... Args>
auto invokeTest(CallableType&& fn, Args&&... args)
{
return std::invoke(fn, args...);
}
有什么区别?
好吧,我会说是,但这要视情况而定。
在这种情况下您不需要转发:
void bar(int);
int main() {
int i = 0;
invokeTest(bar, i);
}
但是,您需要转发这种情况:
void foo(std::unique_ptr<int>);
int main() {
auto p = std::make_unique<int>();
invokeTest(foo, p); // Won't work, cannot copy unique_ptr
}
写std::invoke(fn, args...)
时,args...
都是左值,此时我建议用Args const&...
取参数更清楚。
如果你转发,那么你移动了参数中右值的对象:
template <typename CallableType, typename... Args>
auto invokeTest(CallableType&& fn, Args&&... args)
{
return std::invoke(fn, std::forward<Args>(args)...); // all forward value caterories
}
invokeTest(foo, std::move(p)); // works.
如果您使用 Args&&...
,请使用转发。