I've written the following code, which creates a thread that repeatedly prints a string.
In this code, I can directly pass a string as an argument to the repeat()
function in the main()
function. However, when I want to create a thread that calls the repeat()
function, I have to pass the string inside a std::span
.
Why is this the case? Why does std::thread
require std::span
for a string argument when the repeat()
function itself doesn't?
Errors:
Error C2780: 'std::invoke' expects 1 arguments, 3 provided.
Error C2893: Failed to specialize function template 'std::invoke'.
Visual Studio 2019, Enterprise Edition. 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();
}
std::thread
copies the argument to the decayed type before invoking.
In your example, the string literal decays to const char*
, which is no longer a range, and thus cannot be used to construct a std::span
.