jeudi 21 février 2019

C++: "error: no matching function call" when using std::ref with std::thread in a member function

I have an error that I do not understand when I try to make part of a library I am writing. Can someone please point me in the right direction?

I have a member function that creates two std::threads that both use std::promise and std::ref. I am compiling with CMake and linking the threads library without issue.

Below is a section of my .h file where you can see the functions I want to send my threads to:

object.h

void ThreadFunction1(std::promise<bool> &prom);
void ThreadFunction2(std::promise<bool> &prom, const std::vector<std::string> &things);

Now here is the snippet of code that is causing my build to fail:

object.cpp

bool Object::work(const std::vector<std::string> &things)
{
    // starting point for work mode threads

    // thread 1
    std::promise<bool> prom1;
    std::future<bool> fut1 = prom1.get_future();
    std::thread(&Object::ThreadFunction1, std::ref(prom1), this).detach(); // <<-- this line right here

    // thread 2
    std::promise<bool> prom2;
    std::future<bool> fut2 = prom2.get_future();
    std::thread(&Object::ThreadFunction2, std::ref(prom2), std::ref(things), this).detach(); // <<-- and this line

    if (fut1.get() && fut2.get())
    {
        return true;
    }
    else
    {
        printf("ERROR: work() threads have failed.\n");
        return false;
    }

} // end work

The lines that cause my build to fail are the std::thread(...).detach() lines.

Errors:

/usr/include/c++/7/thread:240:2: error: no matching function for call to ‘std::thread::_Invoker<std::tuple<void (Object::*)(), std::reference_wrapper<std::promise<bool> >, Object> >::_M_invoke(std::thread::_Invoker<std::tuple<void (Object::*)(), std::reference_wrapper<std::promise<bool> >, Object> >::_Indices)’
          operator()()
          ^~~~~~~~

/usr/include/c++/7/thread:258:4: error: no matching function for call to ‘std::tuple<void (Object::*)(), std::reference_wrapper<std::promise<bool> >, Object>::tuple(<brace-enclosed initializer list>)’
          } };
        ^

/usr/include/c++/7/thread:233:29: error: no matching function for call to ‘__invoke(std::__tuple_element_t<0, std::tuple<void (Object::*)(std::promise<bool>&), std::reference_wrapper<std::promise<bool> >, Object*> >, std::__tuple_element_t<1, std::tuple<void (Object::*)(std::promise<bool>&), std::reference_wrapper<std::promise<bool> >, Object*> >, std::__tuple_element_t<2, std::tuple<void (Object::*)(std::promise<bool>&), std::reference_wrapper<std::promise<bool> >, Object*> >)’-> decltype(std::__invoke(_S_declval<_Ind>()...))

And then I get a lot of other errors that are similar. I can post them if needed, but they all start with error: no matching function call for ... I have been looking at this code for days, googling everything I could think of. I looked at What is std::invoke in C++?, I read this reference page, Use member function for std::thread with std::ref(*this) fails to compile, C++11 std::thread giving error: no matching function to call std::thread::thread, and a number of other SO and blog posts about threads.

What I've Tried

I think the issue is std::ref(), but I don't know why. When I test my code with std::thread(&Object::function, this).detach() my code builds fine. I also tested std::ref() in a trivial scrap .cpp file that was not a class/object, it built and ran fine as well. Edit: here us my trivial code test:

using namespace std;

int main(int argc, char *argv[])
{
    promise<bool> promise1;
    future<bool> future1 = promise1.get_future();
    std::thread (ThreadFunction1, ref(promise1)).detach();

    promise<bool> promise2;
    future<bool> future2 = promise2.get_future();
    std::thread thread2(ThreadFunction2, ref(promise2));
    thread2.detach();

    cout << "In Main..." << endl;

    if (future1.get() && future2.get())
    {
        cout << "Everything was a-okay" << endl;
    }
    else
    {
        cout << "Whoops, there was an error..." << endl;
    }

} // end main

void ThreadFunction1(promise<bool> &prom )
{
    cout << "Thread " << this_thread::get_id() << " working in ThreadFunction1!" << endl;
    sleep(10);

    cout << "Thread " << this_thread::get_id() << " finished sleeping in Function1" << endl;
    prom.set_value_at_thread_exit(true);
}

void ThreadFunction2(promise<bool> &prom )
{
    cout << "Thread " << this_thread::get_id() << " working in ThreadFunction2!" << endl;
    sleep(2);
    cout << "Thread " << this_thread::get_id() << " finished sleeping in Function2" << endl;
    prom.set_value_at_thread_exit(true);
}

I tried std::thread(&Object::ThreadFunction1, &prom1, this).detach(); (after looking here) but I received the same errors as above. I tried swapping this and std::ref() like this: std::thread(&Object::ThreadFunction1, this, std::ref(prom1)).detach(); but that didn't fix anything either.

What exactly is going on? What am I missing?

Aucun commentaire:

Enregistrer un commentaire