Search code examples
c++multithreadingthisstdinvoke

Failed to specialize function template 'unknown-type std::invoke(_Callable &&,_Types &&...) noexcept(<expr>)'


Code 1:

class thread_obj {
private:
    static int instances;
    bool run;
    static mutex lock;
    int threadno;
    static map<int, thread> mapOfThreads;
public:
    thread_obj():run(true)
    {
        lock.lock();
        threadno = instances++;
        thread th(thread_obj::thredfunc, this);
        mapOfThreads[threadno] = move(th);

        cout << "Thread no is " << threadno << endl;
        lock.unlock();
    }
    static void thredfunc(thread_obj* ptr)
    {
        while (ptr->run)
        {
            std::this_thread::sleep_for(100ms);
        }
    }

    void operator()()
    {
        while (run)
        {
            std::this_thread::sleep_for(100ms);
        }
    }

    void stop()
    {
        run = false;
    }

    static int getTotalthreads()
    {
        return mapOfThreads.size();
    }

    ~thread_obj()
    {
        lock.lock();
        stop();
        if (mapOfThreads[threadno].joinable())
            mapOfThreads[threadno].join();
        mapOfThreads.erase(threadno);
        cout << "Destroyed " << threadno << endl;
        lock.unlock();
    }
};
int thread_obj::instances = 0;
mutex thread_obj::lock;
map<int, thread> thread_obj::mapOfThreads;

Code 2:

thread_obj():run(true)
{
    lock.lock();
    threadno = instances++;
    thread th(thread_obj(), this);
    mapOfThreads[threadno] = move(th);

    cout << "Thread no is " << threadno << endl;
    lock.unlock();
}

First code works fine, but changing constructor like given in code 2 gives error. In code 1 constructor create thread from static function.In code two constructor calls non static operator()

  1. 'std::invoke': no matching overloaded function found
  2. Failed to specialize function template 'unknown-type std::invoke(_Callable &&,_Types &&...) noexcept(<expr>)'

What is the reason behind this? (This code is created to handle multiple threads.)


Solution

  • This line in the constructor is nonsense:

        thread th(thread_obj(), this);
    

    This will construct another thread_obj() object, then try to invoke it in a new thread passing it the this pointer, i.e. a thread_obj* pointer. That would only work if the operator() function took a thread_obj* argument, but it doesn't.

    I think what you're trying to do is run this->operator()() in a new thread, so you would do that like this:

    thread th(std::ref(*this));
    

    This creates the new thread with a reference to *this and then it will invoke it like (*this)(), which will call operator()(). Alternatively, rename the operator() function to give it a proper name, for example:

    void thread_func()
    {
        while (run)
        {
            std::this_thread::sleep_for(100ms);
        }
    }
    

    And then in the constructor pass a pointer-to-member-function to the std::thread constructor, with this as the object to call that member function on:

    thread th(&thread_obj::thread_func, this);
    

    There are hundreds of existing questions on stackoverflow explaining how to run a member function in a std::thread.