error: no matching function for call to std::thread
Asked Answered
J

2

6

I'm trying to run a function called dcp in a thread, I've to run this function three times independently. So here's how I'm implemented that:

void dcp(cv::Mat&, int, int, cv::Mat&, double);

int main(int argc, char* argv[])
{
cv::Mat IllumTrans;
//fill IllumTrans

std::vector<cv::Mat> rgbDCP;
rgbDCP.reserve(3);
//Fill it

std::thread thread_1(dcp, rgb[0], rows, cols, IllumTrans, A[0]);
std::thread thread_2(dcp, rgb[1], rows, cols, IllumTrans, A[1]);
std::thread thread_3(dcp, rgb[2], rows, cols, IllumTrans, A[2]);

thread_1.join();
thread_2.join();
thread_3.join();
}

But I get that error of no matching function for call:

In file included from 21022018WorksfineOneimageThread.cpp:6:0:
/usr/include/c++/7/thread: In instantiation of ‘struct std::thread::_Invoker<std::tuple<void (*)(cv::Mat&, int, int, cv::Mat&, double), cv::Mat, int, int, cv::Mat, int> >’:
/usr/include/c++/7/thread:127:22:   required from ‘std::thread::thread(_Callable&&, _Args&& ...) [with _Callable = void (&)(cv::Mat&, int, int, cv::Mat&, double); _Args = {cv::Mat&, int&, int&, cv::Mat&, int&}]’
21022018WorksfineOneimageThread.cpp:136:65:   required from here
/usr/include/c++/7/thread:240:2: error: no matching function for call to ‘std::thread::_Invoker<std::tuple<void (*)(cv::Mat&, int, int, cv::Mat&, double), cv::Mat, int, int, cv::Mat, int> >::_M_invoke(std::thread::_Invoker<std::tuple<void (*)(cv::Mat&, int, int, cv::Mat&, double), cv::Mat, int, int, cv::Mat, int> >::_Indices)’
  operator()()
  ^~~~~~~~
/usr/include/c++/7/thread:231:4: note: candidate: template<long unsigned int ..._Ind> decltype (std::__invoke((_S_declval<_Ind>)()...)) std::thread::_Invoker<_Tuple>::_M_invoke(std::_Index_tuple<_Ind ...>) [with long unsigned int ..._Ind = {_Ind ...}; _Tuple = std::tuple<void (*)(cv::Mat&, int, int, cv::Mat&, double), cv::Mat, int, int, cv::Mat, int>]
    _M_invoke(_Index_tuple<_Ind...>)
    ^~~~~~~~~
/usr/include/c++/7/thread:231:4: note:   template argument deduction/substitution failed:
/usr/include/c++/7/thread: In substitution of ‘template<long unsigned int ..._Ind> decltype (std::__invoke(_S_declval<_Ind>()...)) std::thread::_Invoker<std::tuple<void (*)(cv::Mat&, int, int, cv::Mat&, double), cv::Mat, int, int, cv::Mat, int> >::_M_invoke<_Ind ...>(std::_Index_tuple<_Ind1 ...>) [with long unsigned int ..._Ind = {0, 1, 2, 3, 4, 5}]’:
/usr/include/c++/7/thread:240:2:   required from ‘struct std::thread::_Invoker<std::tuple<void (*)(cv::Mat&, int, int, cv::Mat&, double), cv::Mat, int, int, cv::Mat, int> >’
/usr/include/c++/7/thread:127:22:   required from ‘std::thread::thread(_Callable&&, _Args&& ...) [with _Callable = void (&)(cv::Mat&, int, int, cv::Mat&, double); _Args = {cv::Mat&, int&, int&, cv::Mat&, int&}]’
21022018WorksfineOneimageThread.cpp:136:65:   required from here
/usr/include/c++/7/thread:233:29: error: no matching function for call to ‘__invoke(std::__tuple_element_t<0, std::tuple<void (*)(cv::Mat&, int, int, cv::Mat&, double), cv::Mat, int, int, cv::Mat, int> >, std::__tuple_element_t<1, std::tuple<void (*)(cv::Mat&, int, int, cv::Mat&, double), cv::Mat, int, int, cv::Mat, int> >, std::__tuple_element_t<2, std::tuple<void (*)(cv::Mat&, int, int, cv::Mat&, double), cv::Mat, int, int, cv::Mat, int> >, std::__tuple_element_t<3, std::tuple<void (*)(cv::Mat&, int, int, cv::Mat&, double), cv::Mat, int, int, cv::Mat, int> >, std::__tuple_element_t<4, std::tuple<void (*)(cv::Mat&, int, int, cv::Mat&, double), cv::Mat, int, int, cv::Mat, int> >, std::__tuple_element_t<5, std::tuple<void (*)(cv::Mat&, int, int, cv::Mat&, double), cv::Mat, int, int, cv::Mat, int> >)’
    -> decltype(std::__invoke(_S_declval<_Ind>()...))
                ~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~
In file included from /usr/include/c++/7/tuple:41:0,
                 from /usr/include/c++/7/functional:54,
                 from /usr/local/include/opencv2/core/utility.hpp:60,
                 from /usr/local/include/opencv2/core.hpp:3261,
                 from 21022018WorksfineOneimageThread.cpp:1:
/usr/include/c++/7/bits/invoke.h:89:5: note: candidate: template<class _Callable, class ... _Args> constexpr typename std::__invoke_result<_Functor, _ArgTypes>::type std::__invoke(_Callable&&, _Args&& ...)
     __invoke(_Callable&& __fn, _Args&&... __args)
     ^~~~~~~~
/usr/include/c++/7/bits/invoke.h:89:5: note:   template argument deduction/substitution failed:
/usr/include/c++/7/bits/invoke.h: In substitution of ‘template<class _Callable, class ... _Args> constexpr typename std::__invoke_result<_Functor, _ArgTypes>::type std::__invoke(_Callable&&, _Args&& ...) [with _Callable = void (*)(cv::Mat&, int, int, cv::Mat&, double); _Args = {cv::Mat, int, int, cv::Mat, int}]’:
/usr/include/c++/7/thread:233:29:   required by substitution of ‘template<long unsigned int ..._Ind> decltype (std::__invoke(_S_declval<_Ind>()...)) std::thread::_Invoker<std::tuple<void (*)(cv::Mat&, int, int, cv::Mat&, double), cv::Mat, int, int, cv::Mat, int> >::_M_invoke<_Ind ...>(std::_Index_tuple<_Ind1 ...>) [with long unsigned int ..._Ind = {0, 1, 2, 3, 4, 5}]’
/usr/include/c++/7/thread:240:2:   required from ‘struct std::thread::_Invoker<std::tuple<void (*)(cv::Mat&, int, int, cv::Mat&, double), cv::Mat, int, int, cv::Mat, int> >’
/usr/include/c++/7/thread:127:22:   required from ‘std::thread::thread(_Callable&&, _Args&& ...) [with _Callable = void (&)(cv::Mat&, int, int, cv::Mat&, double); _Args = {cv::Mat&, int&, int&, cv::Mat&, int&}]’
21022018WorksfineOneimageThread.cpp:136:65:   required from here
/usr/include/c++/7/bits/invoke.h:89:5: error: no type named ‘type’ in ‘struct std::__invoke_result<void (*)(cv::Mat&, int, int, cv::Mat&, double), cv::Mat, int, int, cv::Mat, int>’

I'm compiling my program like that:

g++ -std=c++1z -fomit-frame-pointer -O3 -ffast-math -mmmx -msse -msse2 -msse3 -DNDEBUG -Wall 21022018WorksfineOneimageThread.cpp -o 21022018WorksfineOneimageThread -fopenmp `pkg-config --cflags --libs opencv`

gcc version 7.3.0 (Ubuntu 7.3.0-16ubuntu3~16.04.1) 
Jerilynjeritah answered 13/5, 2018 at 14:53 Comment(6)
Possible duplicate of std::thread pass by reference calls copy constructorIllstarred
You are missing a bunch of headers, including the one std::thread is defined in.Lovering
@Illstarred I couldn't guess that I need to pass y reference!Jerilynjeritah
@Lovering I didn't include any includes in my post and this is not the issueJerilynjeritah
@Jerilynjeritah You should post a minimal reproducible example.Lovering
I ran into a similar problem whenever I called a function of an array of a variable length just fyi.Selfeffacing
C
20

Your function expects a reference (cv::Mat&) as its first and fourth arguments, but you're passing just cv::Mat, so you should wrap these in std::ref:

std::thread thread_1(dcp, std::ref(rgb[0]), rows, cols, std::ref(IllumTrans), A[0]);
Currycomb answered 13/5, 2018 at 14:57 Comment(2)
That solve my issue. I want to know how could I know that the function expects a reference from the error I got?Jerilynjeritah
@Ja_cpp, the second line says: /usr/include/c++/7/thread: In instantiation of ‘struct std::thread::_Invoker<std::tuple<void (*)(cv::Mat&, int, int, cv::Mat&, double), cv::Mat, int, int, cv::Mat, int> >’:. So, the first template argument to std::thread::_Invoker holds the types of the function's arguments.Currycomb
L
1

I'd like to point out something in case someone runs into the same problem as me.

I had a similar problem where I was launching a thread from within a const member function. The function that the thread was going to execute wasn't const because it needed to modify the member variables of the object that created it, but since the this pointer was const due to being called from a const function the compiler complained with an error similar to OP's.

I can't share my code but I'll share something similar to demonstrate the issue.

void FooClass::setup() const  // The const here was my problem
{
  // Here, the 'this' pointer is const due to the setup function being const
  // but the thread_routine function expects it no to be const.
  std::thread(&FooClass::thread_routine, this).detach();
}

void FooClass::thread_routine()
{
  // Do something with member variables
}

Hope this helps anyone in the future.

Lorentz answered 27/3, 2020 at 16:44 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.