【问题标题】:What does `decay_copy` in the constructor in a `std::thread` object do?`std::thread` 对象的构造函数中的`decay_copy` 有什么作用?
【发布时间】:2021-08-29 00:50:59
【问题描述】:

我试图理解 std::thread 的构造函数,但无法理解参数类型是如何表示/处理的。从cppreference来看,一个简化的构造函数可以画成如下:

class thread {
   public:
    template <class Function, class Arg>
    thread(Function&& f, Arg&& arg) {
        // something happening
        std::invoke(decay_copy(std::forward<Function>(f)),
                    decay_copy(std::forward<Arg>(arg)));
        // something else happening
    }
};

cppreference 将decay_copy 定义为:

template <class T>
std::decay_t<T> decay_copy(T&& v) { return std::forward<T>(v); }

我对以下示例进行了一些实验:

struct X{};
int main() {
    X x1{};
    X& x2 = x1;
    auto f = []() { return; };
    thread t1{f, x1}; // arg should be of type X& after the inner std::forward<Arg>(arg);
    thread t2{f, x2}; // arg should be of type X& after the inner std::forward<Arg>(arg);
    thread t3{f, X{}}; // arg should be of type X&& after the inner std::forward<Arg>(arg);
}

根据我的分析,x1x2 在内部std::forward 之后都是左值引用类型,而X{} 是右值引用类型。我相信我们需要以某种方式将x1x2 分开以通过值或引用传递它。分析让我想到三个问题:

  • 上面的分析正确吗?
  • decay_copy 如何正确解开类型?
  • 在此开始了一段时间后,我想知道:哦,麻烦,为什么会如此涉及?可以更轻松地完成吗?答案当然是否定的,但我对整个操作仍然缺乏直觉。

感谢任何提示、建议或解释!

【问题讨论】:

    标签: c++ multithreading c++11 templates types


    【解决方案1】:

    Std 线程复制(或移动)到参数类型的衰减版本。衰减的版本不是引用,也不是 const 也不是 volatile 也不是数组(数组和函数变成指针)。

    如果您想要一个左值引用参数,请使用引用包装器。否则线程ctor中被调用的函数将获得一个右值;衰减副本只是确定您在线程函数中传递的右值是如何从您的 std 线程参数构造的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-22
      • 1970-01-01
      • 1970-01-01
      • 2020-03-06
      • 2022-12-23
      相关资源
      最近更新 更多