volperossa
volperossa

Reputation: 1431

std::thread overload not resolved (with right arguments)

#include <thread>
#include <iostream>
using namespace std;

class A
{
    public:
    A(){}
    void m(std::string* s)
    {
     cout<<*s;
    }
    void m(std::string s)
   {
     cout<<s;
   }
};    

int main()
{
 A a;
 string str="hi!\n";
 std::thread(&A::m,a,&str);

}

this doesn't compile; it gives:

error: no matching function for call to ‘std::thread::thread(<unresolved overloaded function type>, A&, std::string*)’

if I remove the second member it compiles! why? I can't use overloaded methods in std::thread?

Upvotes: 1

Views: 874

Answers (1)

Wintermute
Wintermute

Reputation: 44043

You can, but you have to pick the desired overload manually:

std::thread th(static_cast<void (A::*)(std::string*)>(&A::m),a,&str);

Or you could use a lambda:

std::thread th([&] { a.m(&str); });

Addendum: The reason this can't be deduced automatically is, in short, that the compiler looks only skin-deep when searching for the right constructor. Finding (making!) the right constructor from the relevant constructor template of the std::thread class involves template argument deduction, and template argument deduction looks, as a rule, only at the signatures and not the internals of a function template (in this case a constructor template, which is for our purposes the same). The relevant constructor template is

template< class Function, class... Args >
explicit thread( Function&& f, Args&&... args );

...which does not in itself say anything about the interplay of f and args in the depths of the implementation. There is not enough information in it to decide that only one overrload of A::m can work, so the ambiguity cannot be resolved, and you have to do it manually.

Whether it is actually possible and/or practical to make the compiler look deeper to resolve such ambiguities is an interesting question. I imagine it would be quite a challenge. Either way, it has not yet been done.

Upvotes: 6

Related Questions