简体   繁体   中英

C++: does std::invoke need perfect forwarding?

Snippet

template <typename CallableType, typename... Args>
auto invokeTest(CallableType&& fn, Args&&... args)
{
    return std::invoke(fn, std::forward<Args>(args)...);
}

Is std::forward<Args> needed here? Or is it enough to write

template <typename CallableType, typename... Args>
auto invokeTest(CallableType&& fn, Args&&... args)
{
    return std::invoke(fn, args...);
}

What are the differences?

Well, I'd say yes but it depends on the case.

You don't need forwarding in that case:

void bar(int);

int main() {
    int i = 0;
    invokeTest(bar, i);
}

But, you'll need forwarding for this case:

void foo(std::unique_ptr<int>);

int main() {
    auto p = std::make_unique<int>();
    invokeTest(foo, p); // Won't work, cannot copy unique_ptr
}

When writing std::invoke(fn, args...) , the args... are all lvalues, at which point I would recommend taking parameters by Args const&... to be clearer.

If you forward, then you move the object that were rvalues in your parameters:

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.

If you use Args&&... , use forwarding.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM