我试图弄清楚在下面的代码中使用std::forward是否有意义,即使它不是一个转发(=通用)引用。请原谅代码的数量,但这是我试图实现的精简版本。
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;
};这样做的想法是,如果传递给add()的可调用函数不返回bool,我们将将其包装在一个具有此功能的lambda中。
现在,如果我直接传递args...,它将始终工作,但是如果Args中的任何一个是rvalue,那么它将不必要地执行一个副本而不是移动。如果我使用的是std::move(args)...,那么如果Args中的任何一个是lvalue,它就不能工作。在这里使用std::forward<Args>(args)...似乎解决了这些问题,并且在任何情况下都尽可能高效地工作,但我担心我遗漏了一些东西,因为我使用std::forward进行非转发引用,而且通常,我在整个引用中遇到很多麻烦--崩溃/ rvalue引用/ std::move /std::正向问题。
发布于 2018-02-20 17:27:26
std::move不移动,std::forward不向前移动。
std::forward是一个有条件的动作。如果std::forward<T>是值或rvalue引用,则T会移动。
这与您想要移动args...的时间是一致的,所以在这里是合适的。
这样的注释应该是个好主意,就像在简单转发引用之外使用std::forward的任何情况一样。
https://stackoverflow.com/questions/48885599
复制相似问题