create thread with function taking vector argument fails

I'm creating a thread to run a function sample(vector<double>&) and compilation give me errors. I don't understand the error messages. Any help is appreciated. I'm compiling on linux.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <iostream>
#include <vector>
#include <thread>

using namespace std;

void sample(vector<double>& v) { }

int main() {
    vector<double> some_vec {1,2,3,4,5,6,7,8,9};
    thread t2 {sample,some_vec};
    t2.join();
    return 0;
}


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
ninja: Entering directory `build'
[1/2] c++ -Iappname@exe -I. -I.. -fdiagnostics-color=always -pipe -D_FILE_OFFSET_BITS=64 -Wall -Winvalid-pch -Wnon-virtual-dtor -Wextra -Wpedantic -std=gnu++2a -g -pthread -MD -MQ 'appname@exe/appname.cpp.o' -MF 'appname@exe/appname.cpp.o.d' -o 'appname@exe/appname.cpp.o' -c ../appname.cpp
FAILED: appname@exe/appname.cpp.o 
c++ -Iappname@exe -I. -I.. -fdiagnostics-color=always -pipe -D_FILE_OFFSET_BITS=64 -Wall -Winvalid-pch -Wnon-virtual-dtor -Wextra -Wpedantic -std=gnu++2a -g -pthread -MD -MQ 'appname@exe/appname.cpp.o' -MF 'appname@exe/appname.cpp.o.d' -o 'appname@exe/appname.cpp.o' -c ../appname.cpp
../appname.cpp: In function ‘void sample(std::vector<double>&)’:
../appname.cpp:7:29: warning: unused parameter ‘v’ [-Wunused-parameter]
    7 | void sample(vector<double>& v) { }
      |             ~~~~~~~~~~~~~~~~^
../appname.cpp: In function ‘int main()’:
../appname.cpp:11:31: error: no matching function for call to ‘std::thread::thread(<brace-enclosed initializer list>)’
   11 |     thread t2 {sample,some_vec};
      |                               ^
In file included from ../appname.cpp:3:
/usr/include/c++/9/thread:144:5: note: candidate: ‘std::thread::thread(std::thread&&)’
  144 |     thread(thread&& __t) noexcept
      |     ^~~~~~
/usr/include/c++/9/thread:144:5: note:   candidate expects 1 argument, 2 provided
/usr/include/c++/9/thread:117:7: note: candidate: ‘template<class _Callable, class ... _Args, class> std::thread::thread(_Callable&&, _Args&& ...)’
  117 |       thread(_Callable&& __f, _Args&&... __args)
      |       ^~~~~~
/usr/include/c++/9/thread:117:7: note:   template argument deduction/substitution failed:
../appname.cpp:11:31: note:   couldn’t deduce template parameter ‘_Callable’
   11 |     thread t2 {sample,some_vec};
      |                               ^
In file included from ../appname.cpp:3:
/usr/include/c++/9/thread:112:5: note: candidate: ‘std::thread::thread()’
  112 |     thread() noexcept = default;
      |     ^~~~~~
/usr/include/c++/9/thread:112:5: note:   candidate expects 0 arguments, 2 provided
ninja: build stopped: subcommand failed. 


Last edited on
In order to pass a reference to a thread you need to use std::ref(...):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <iostream>
#include <vector>
#include <thread>

using namespace std;

void sample(vector<double>& v) { }

int main() {
    vector<double> some_vec {1,2,3,4,5,6,7,8,9};
    thread t2 {sample,std::ref(some_vec)}; // Note
    t2.join();
    return 0;
}
Otherwise the initializer list cannot tell that it is a reference and tries to use it as a copy.

See:
https://www.cplusplus.com/reference/functional/ref/
Hi

Edit: I didn't see the previous post.

The sample function is expecting a reference, also compiler doesn't like brace initialisation here. The following compiles on cpp.sh under c++14.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <iostream>
#include <vector>
#include <thread>

//using namespace std;

void sample(std::vector<double>& v) { }

int main() {
    std::vector<double> some_vec {1,2,3,4,5,6,7,8,9};
    std::thread t2 (sample,std::ref(some_vec));
    t2.join();
    return 0;
}


7:29: warning: unused parameter 'v' [-Wunused-parameter]


I removed line 5, it will bite you in the ass one day :+)

You could of figured this out yourself if you had looked at the documentation:

https://en.cppreference.com/w/cpp/thread/thread/thread
Last edited on
I have discovered that, following from the original example...

When...
void sample(vector<double>& v) { }
is changed to...
void sample(const vector<double>& v) { }
then I wouldn't need to use std::ref and compilation is successful.

Could someone explain why that is?
Last edited on
It's in the documentation.
https://en.cppreference.com/w/cpp/thread/thread/thread

std::thread::thread calls
1
2
std::invoke(decay_copy(std::forward<Function>(f)), 
            decay_copy(std::forward<Args>(args))...);

The calls to decay_copy are prvalue expressions, so the vector is copied.

See also this post:
https://www.cplusplus.com/forum/general/273175/#msg1178146
Last edited on
Registered users can post here. Sign in or register to post.