简体   繁体   中英

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;
}

If you have an overloaded function and want to pick a specific overload, you have to cast it manually to get the right one like:

std::thread t1(static_cast<void(*)(const std::string&, std::shared_ptr<MySem>)>(&fun<MyData, MySem>),
        std::string("this doesn't"),
        std::make_shared<MySem>());               // line 43

As already given in the comment from "Passer By", using a lambda simplifies the whole thing a lot and makes the code more readable.

See also here: other answer

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>());});

The problem is not related with the std::thread function, the problem is that the compiler does not know which overloaded function you are requesting, using a lambda as a workaround could do the job:

    std::thread t1([=]{ 
        fun<MyData, MySem>(std::string("This doesn't"),  std::make_shared<MySem>()); 
        } );
    t1.join();

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM