Calling overloaded member functions using std::thread

Ram picture Ram · Jan 11, 2013 · Viewed 8.1k times · Source

Is it possible to have overloads for functions that we need to span using threads ?

I have a simple class called Complex.

class Complex
{
public:
    Complex():realPart_(0), imagPart_(0){}

    Complex(double rp, double ip) : realPart_(rp), imagPart_(ip) {}

    double & real() { return realPart_;}
    double & imag() { return imagPart_;}

    const double & real() const { return realPart_;}
    const double & imag() const { return imagPart_;}

    double square() const {return realPart_*realPart_ - imagPart_*imagPart_;}

    void display() const
    {
        std::cout << "Square of the Complex number (" << realPart_ << ") + i (" << imagPart_ << " ) is " << square() << std::endl;  
    }

    void display(unsigned nTimes) const {while(nTimes-- > 0)display();}

private:

    double realPart_;
    double imagPart_;

};

void Test3()
{
    Complex c1(1, 0.74), c2(2, 0.35);

    std::thread sqCalc1(&Complex::display, &c1);
    std::thread sqCalc2(&Complex::display, &c2);

    sqCalc1.join();
    sqCalc2.join();
}

I get errors when I build this code.

error C2661: 'std::thread::thread' : no overloaded function takes 2 arguments

If there is no overloaded display function that takes an unsigned then the code I have shown works fine.

Answer

Jonathan Wakely picture Jonathan Wakely · Jan 13, 2013

The problem is nothing to do with std::thread (the error is misleading), as can be shown by rearranging the code:

auto memfunc = &Complex::display;
std::thread sqCalc1(memfunc, &c1);
std::thread sqCalc2(memfunc, &c2);

The error will be on the first line now, because as other answers have said, the expression &Complex::display refers to an overloaded function and the compiler doesn't know which one you mean.

You can select the desired overload by telling the compiler the type of the function you are trying to call, with a cast or like this:

void (Complex::*memfunc)() const = &Complex::display;
std::thread sqCalc1(memfunc, &c1);
std::thread sqCalc2(memfunc, &c2);

Now you've explicitly requested the display overload that returns void and takes no arguments.

If your compiler supports C++11 alias declarations you can make that easier to read:

using memfunc_type = void (Complex::*)() const;
memfunc_type memfunc = &Complex::display;
std::thread sqCalc1(memfunc, &c1);
std::thread sqCalc2(memfunc, &c2);