为什么在 C++ 中使用 std::thread 时需要为字符串参数传递 std::span?

Why do I need to pass std::span for a string argument when using std::thread in C++?

提问人:Sami 提问时间:7/16/2023 最后编辑:Remy LebeauSami 更新时间:7/17/2023 访问量:190

问:

我编写了以下代码,该代码创建了一个重复打印字符串的线程。

在此代码中,我可以直接将字符串作为参数传递给函数中的函数。但是,当我想创建一个调用该函数的线程时,我必须将字符串传递到 .repeat()main()repeat()std::span

为什么会这样?为什么需要字符串参数,而函数本身不需要?std::threadstd::spanrepeat()

错误:

Error C2780: 'std::invoke' expects 1 arguments, 3 provided.
Error C2893: Failed to specialize function template 'std::invoke'.

Visual Studio 2019 企业版。C++20

#include <span>
#include <iostream>

void repeat1(std::span<const char> str, int n)
{
    if (n > 0)
    {
        std::cout << str.data() << std::endl;
        repeat1(str, n - 1);
    }
}

void repeat2(std::string_view str, int n)
{
    if (n > 0)
    {
        std::cout << str.data() << std::endl;
        repeat2(str, n - 1);
    }
}

int main()
{
    repeat1("I am exploring...", 3); //it works 
    repeat2("I am exploring...", 3); //it works 
    //std::thread t(repeat2, "I am exploring...", 5); // It works
    //std::thread t(repeat1, std::span < const char>("I am exploring..."), 5); // It works
    std::thread t(repeat1, "I am exploring...", 5); // It doesn't compile
    std::cout << "Hello from main()\n";
    t.join();
}
C++ 多线程 C++20 标准跨度

评论

2赞 Some programmer dude 7/16/2023
如果你不使用 ,会发生什么?这给你带来了什么问题?请编辑您的问题,以便向我们提供更多详细信息。std::span
1赞 Some programmer dude 7/16/2023
或者你的意思是为什么你不能做,但你可以直接打电话?(我无法复制)同样,请编辑您的问题以详细说明,向我们提供更多详细信息,如果您遇到构建错误,请也包括它们。另外,请确保您向我们展示了失败代码的适当最小可重现示例,并告诉我们您正在使用的编译器及其版本。以及构建时使用的标志和选项。std::thread t(repeat, str, 5);repeat(str, 5)
0赞 Pepijn Kramer 7/16/2023
您根本不需要传递 std::span。使用 lambda 表达式,您可以轻松地以您指定的模式(引用或复制)捕获任何类型的对象
0赞 Sami 7/16/2023
@Someprogrammerdude我已经编辑了代码。对不起,不清楚。

答:

4赞 康桓瑋 7/16/2023 #1

std::thread在调用之前将参数复制到衰减类型。

在您的示例中,字符串文字衰减为 ,它不再是一个范围,因此不能用于构造 .const char*std::span