c++ - 根据函数签名将可变参数模板中的类型转发为值/引用

标签 c++ variadic-templates stdthread perfect-forwarding

这个问题与this有关, this并且可能是 this .

我有以下类(class),其中 AddFunction方法接收一个函数和该函数的参数列表,然后生成一个 std::thread使用传递的参数调用传递的函数:

class Processes {
public:
  Processes() {}

  ~Processes() {
    for (auto &t : threads_) {
      t.join();
    }
  }

  template <class Function, typename... Args>
  void AddFunction(Function &&func, Args &&... args) {
    threads_.emplace_back(std::forward<Function>(func),
                          std::forward<Args>(args)...);
  }

private:
  std::vector<std::thread> threads_;
}

这会导致每个参数都有一个拷贝,如果对象不可复制,编译将失败,因为 std::thread需要将引用包裹在 std::ref 中为了保证这个对象会超过线程的生命周期,否则将复制它。

我想在目标函数签名中指定时通过引用传递对象

我尝试使用 lambda:

template <class Function, typename... Args>
void AddFunction(Function &&func, Args &&... args) {
  threads_.emplace_back([&]() { func(std::forward<Args>(args)...); });
}

但这会导致不正确的行为,因为 lambda 在按值传递值之前通过引用捕获值,从而导致通过引用捕获行为。

如何实现根据目标函数签名将参数作为值或引用转发的函数?


示例:

void Foo(int a, std::vector<int> const &b) { /* ... */ }

int main() {
  Processes procs;
  int a = 6;
  std::vector<int> b;
  procs.AddFunction(
    Foo,
    a, // Should be passed by value
    b  // Should be passed by reference (as implemented by std::ref)
  );
  return 0;
}

最佳答案

您可以将函数签名更改为不那么通用:

首先是一些助手:

template <typename T> struct non_deducible { using type = T; };
template <typename T> using non_deducible_t = typename non_deducible<T>::type;

template <typename T>
auto passed_by(T& t, std::true_type)
{
    return std::ref(t);
}

template <typename T>
T&& passed_by(T&& t, std::false_type)
{
    return std::forward<T>(t);
}

然后

template <class Ret, typename... Args>
void AddFunction(Ret (*func)(Args...), non_deducible_t<Args>... args) {
    threads_.emplace_back(func,
                          passed_by(std::forward<Args>(args),
                                    std::is_reference<Args>{})...);
}

关于c++ - 根据函数签名将可变参数模板中的类型转发为值/引用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47037395/

相关文章:

c++ - constexpr 未定义行为

c++ - 使用 Variadic 模板的困难

c++ - 有没有类似 pthread_create 的 std::thread_create?

c++ - 对 `vtable for MainWindow' 的 undefined reference

c++ - 如何在QTableWidget中进入单元格编辑时弹出QCompleter

c++ - 在 boost 二进制文件上使用显式位置编译 boost 标志

c++ - 可变参数模板参数

c++ - 将函数作为可变参数模板参数传递,并调用它们

multithreading - 在 Mac OS X 上使用 clang 创建 std::thread 时出错: "attempt to use a deleted function"

c++ - 标准线程 sleep_for 不适用于某些 chrono::duration