Search code examples
c++c++11shared-ptrrvalue-referencestdthread

no matching function for call to <unresolved overloaded function type>


I can't relate with similar questions. That's my MRE, basically I'd like to overload fun with a version accepting a template reference. It all works until std::thread enters in the game. It seems I'm missing something from its constructor.

Error shown on g++-10 is

error: no matching function for call to ‘std::thread::thread(<unresolved overloaded function type>, std::string, std::shared_ptr<MySem>)’
   43 |   std::make_shared<MySem>());
#include <string>
#include <memory>
#include <thread>

class MyData
{};

class MySem
{};

template <typename T, typename Sem>
void fun(T & t, const std::string & TAG, std::shared_ptr<Sem> upSem)
{}

template <typename T, typename Sem>
void fun(const std::string & TAG, std::shared_ptr<Sem> upSem)
{
    T t;
    fun(t, TAG, upSem);  // NO std::ref(t)
}

int main(int argc, char ** argv)
{
    MyData d;

    fun<MyData, MySem>(
        "works",
        std::make_shared<MySem>());

    fun<MyData, MySem>(
        d,
        "this too",
        std::make_shared<MySem>());


    std::thread t1(fun<MyData, MySem>,
        std::string("this doesn't"),
        std::make_shared<MySem>());               // line 43

    std::thread t2(fun<MyData, MySem>,
        d,
        std::string("this neither"),
        std::make_shared<MySem>());

    return 0;
}

Solution

  • My guess is that the constructor of std::thread cannot resolve which overload of fun you're trying to call. No idea why though.

    Having only one version of fun such as

    template <typename T, typename sem>
    void fun(const std::string&, std::shared_ptr<sem>)
    {
        ...
    }
    

    Allows you to construct t1 fine (but t2 will obviously fail).

    A workaround is to pass a lambda instead, such as:

    std::thread t3([&](){fun<data, sem>(d, "works again", std::make_shared<sem>());});
    std::thread t4([&](){fun<data, sem>("this too", std::make_shared<sem>());});