c++ - 将 std::forward 用于非转发引用

标签 c++ c++11 c++17

我想知道我是否使用了 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中的任何一个|是右值,那么它将不必要地进行复制而不是移动。如果我改为使用 std::move(args)...如果Args中的任何一个,它将不起作用是一个左值。使用 std::forward<Args>(args)...这里似乎解决了这些问题并在任何情况下都尽可能高效地工作,但我担心我在使用 std::forward 时遗漏了一些东西。对于非转发引用,一般来说,我在思考整个引用折叠/右值引用/std::move/std::forward 问题时遇到了很多麻烦。

最佳答案

std::move不动std::forward不转发。

std::forward是一个有条件的举动std::forward<T>如果 T 移动是值或右值引用。

这与您要移动的时间一致 args... , 所以在这里是合适的。

按照这些行进行评论应该是个好主意,因为在您使用 std::forward 的任何情况下在简单的转发引用之外。

关于c++ - 将 std::forward 用于非转发引用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48885599/

相关文章:

c++ - 重载下标运算符不返回指针

c++ - 更新存储在 map 中的 vector vector

c++ - 在 C++11 中实现元函数 zip

c++ - 将单词存储在字符串指针中

c++ - 可变参数模板与使用元组在参数中添加不同的数据对

c++ - 模板化参数中仿函数的默认参数

c++ - 如果没有 noexcept 移动构造函数,为什么带有 std::vector 的代码不能编译,但带有 std::unique_ptr 的代码可以编译?

c++ - 在哪里可以找到 std::bitset 的数据成员?

c++ - 显式赋值与隐式赋值

c++ - C++11 中的 vector <字符> VS vector < bool >