dimanche 3 mars 2019

Compilation error when passing a string to thread function expecting a reference to a string [duplicate]

This question already has an answer here:

I am trying to understand the root cause of the compilation error that I get when the trying to compile the following:

#include <iostream>
#include <string>
#include <thread>
#include <type_traits>

using namespace std;
using namespace std::chrono;

void function(string& str) {
  std::reverse(str.begin(), str.end());
  cout << "In thread function after reverse: " << str << endl;
}

int main(int argc, char* argv[]) {
 std::string string_main("I am not modified");
  cout << "Before: " << string_main << endl;

  thread t1(function, string_main);
  t1.join();

  cout << "After: " << string_main << endl;
  return 0;
}

  1. I know that this should not be done and it would not even behave as expected.
  2. I also know that a simple std::ref would make this code compile just fine.

    /usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/8.2.1/../../../../include/c++/8.2.1/thread:120:2: error: static_assert failed due to requirement '__is_invocable, allocator > &)>::type, typename decay, allocator > &>::type>::value' "std::thread arguments must be invocable after conversion to rvalues" static_assert( __is_invocable::type, ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ tutorial3.cpp:34:10: note: in instantiation of function template specialization 'std::thread::thread, std::allocator > &), std::__cxx11::basic_string, std::allocator > &, void>' requested here thread t1(function, string_main); ^ In file included from tutorial3.cpp:6: /usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/8.2.1/../../../../include/c++/8.2.1/thread:252:40: error: no matching member function for call to '_M_invoke' -> decltype(std::declval<_Invoker&>()._M_invoke(_Indices()))

The error that I get basically boils down to

static_assert failed due to requirement...
std::thread arguments must be invocable after conversion to rvalues

According to the error it looks like that the thread is instantiated in the following manner:

tutorial3.cpp:34:10: note: in instantiation of function template specialization
'std::thread::thread<void (&)(std::__cxx11::basic_string<char...> &), std::__cxx11::basic_string<char... > &, void>' requested here
  thread t1(function, string_main);

string_main is taken as a reference to a string in the thread constructor but somehow the following assert is failing:

__is_invocable<typename decay<void (&)(basic_string<char...> &)>::type, typename decay<basic_string<char...> &>::type>::value'

Is it failing because decay is removing the reference to string_main and __is_invocable returns true only if the parameters match the function signature exactly?

I believe this is the right explanation even because the following assert fails:

 static_assert( std::is_invocable<void(string&), std::string>::value );

Apparently std::is_invocable does not allow a void(string&) to be called with a std::string.

Aucun commentaire:

Enregistrer un commentaire