Reputation: 21508
I am trying to figure out if my use of std::forward
in the following code makes sense even though it is not a forwarding (=universal) reference. Please excuse the amount of code, but this is the stripped-down version of what I am trying to achieve.
template <class... Args>
class event_dispatcher {
private:
using func_t = std::function<bool(Args...)>;
public:
bool operator()(Args... args) const {
for (auto& f : funcs) {
if (!f(args...))
return false;
}
return true;
}
template <class F>
std::enable_if_t<std::is_invocable_r_v<bool, F, Args...>>
add(F&& f) {
funcs.emplace_back(std::forward<F>(f));
}
template <class F>
std::enable_if_t<!std::is_invocable_r_v<bool, F, Args...> && std::is_invocable_v<F, Args...>>
add(F&& f) {
add([f_ = std::forward<F>(f)](Args... args){
std::invoke(f_, std::forward<Args>(args)...); // <-- this is the one I am asking about!
return true;
});
}
private:
std::vector<func_t> funcs;
};
The idea is that if the callable passed to add()
doesn't return a bool
, we will wrap it in a lambda that does.
Now, if I just pass args...
directly, it will always work, but if any of Args
are rvalues then it will needlessly do a copy instead of a move. If I instead use std::move(args)...
it will not work if any of Args
is an lvalue. Using std::forward<Args>(args)...
here seems to solve these problems and work as efficiently as possible in any case, but I am worried that I am missing something since I am using std::forward
for a non-forwarding reference, and in general I am having a lot of trouble wrapping my head around the whole reference collapsing / rvalue reference / std::move / std::forward issues.
Upvotes: 3
Views: 571
Reputation: 275330
std::move
does not move std::forward
does not forward.
std::forward
is a conditional move. std::forward<T>
moves if T
is a value or rvalue reference.
This lines up with when you want to move args...
, so it is appropriate here.
A comment along those lines should be a good idea, as in any situation where you use std::forward
outside of simple forwarding references.
Upvotes: 3