C++ 根据函数签名将变量模板中的类型转发为值/引用

C++ 根据函数签名将变量模板中的类型转发为值/引用,c++,variadic-templates,stdthread,perfect-forwarding,C++,Variadic Templates,Stdthread,Perfect Forwarding,这个问题涉及到,并且可能涉及 我有一个类,其中AddFunction方法接收一个函数和该函数的参数列表,然后生成一个std::thread,用传递的参数调用传递的函数: class Processes { public: Processes() {} ~Processes() { for (auto &t : threads_) { t.join(); } } template <class Function, typename...

这个问题涉及到,并且可能涉及

我有一个类,其中
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_;
}
但这会导致不正确的行为,因为lambda在通过值传递值之前通过引用捕获值,从而导致通过引用捕获行为

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


例如:

voidfoo(inta,std::vector const&b){/*…*/}
int main(){
过程;
INTA=6;
std::载体b;
procs.AddFunction(
福,
a、 //应按值传递
b//应通过引用传递(由std::ref实现)
);
返回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);
}
模板结构不可推断{using type=T;};
使用non_deducible_t=typename non_deducible::type的模板;
模板
自动通过(T&T,标准::真实类型)
{
返回std::ref(t);
}
模板
T&&T通过(T&&T,标准::错误类型)
{
返回std::向前(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>{})...);
}
模板
void AddFunction(Ret(*func)(参数…,不可推断的参数){
线程放置回(函数,
通过(标准::转发(args),
std::is_reference{})…);
}

如果您想沿着lambda路线走下去,您可以实现一些实用程序,这意味着右值被移动到闭包中,左值通过引用被捕获。您可以使用
std::tuple
存储
T
T&
(我的链接文章有一个更清晰的实现):

模板
void AddFunction(函数和函数,参数和…参数)
{
线程。将线程放置回([

targs=std::tuple

这解决了问题。我不知道你可以用这种方式解压函数调用。什么是
{}
语法?那只是一个空构造函数吗?谢谢!是的,
类型{}
类型
的空构造函数,使用
{}
语法可以避免在某些情况下与
类型()相反的麻烦解析
(即使在这里两者都可以工作)。
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>{})...);
}
template <class Function, typename... Args>
void AddFunction(Function &&func, Args &&... args) 
{
    threads_.emplace_back([
        targs = std::tuple<Args...>{std::forward<Args>(args)...},
        tfunc = std::tuple<Function>(func)]() mutable
    { 
        std::apply([&targs](auto&& x_func)
        {
            std::apply([&x_func](auto&&... x_args)
            { 
                std::forward<Function>(x_func)(
                    std::forward<Args>(x_args)...
                );
            }, targs);
        }, tfunc);
    });
}