7

Possible Duplicate:
Start thread with member function

I'm VERY new to C++. My experience has mostly been with javascript and java.

I'm using Xcode on Lion. The following code gives me a compilation error "Reference to non-static member function must be called; did you mean to call it with no arguments?"

class MyClass {
private:
    void handler() {
    }

public:
    void handleThings() {
        std::thread myThread(handler);
    }
};

I also tried this->handler, &handler, and other variations, but none of them worked. This code compiles though and accomplishes what I want it to:

class MyClass {
private:
    void handler() {
    }

public:
    void handleThings() {
        std::thread myThread([this]() {
            handler();
        });
    }
};

Why can't I pass a reference to a member function? Is my work-around the best solution?

Community
  • 1
  • 1
Trevor Dixon
  • 23,216
  • 12
  • 72
  • 109
  • 2
    that is not a "workaround"... that is the right way to do your task (one of). the second one, is to use `std::bind` instead of lambda. to call a method of a class you have to provide an instance of that class (`this` pointer as first implicit parameter of any non static member-function). passing just an address of the method you want to call (w/o the instance) to `std::thread` ctor is not enough obviously. – zaufi Jan 22 '13 at 07:14
  • depending on your tasks consider to use `std::async` instead of `std::thread`... in case if running thread just calc smth and exits (i.e. not an even loop handler) – zaufi Jan 22 '13 at 07:28
  • I get it now. Your first comment zaufi as well as this answer http://stackoverflow.com/a/12765270/711902 taught me something. – Trevor Dixon Jan 22 '13 at 07:28

3 Answers3

17
std::thread myThread(&MyClass::handler, this);
myThread.join();
Pete Becker
  • 74,985
  • 8
  • 76
  • 165
5

You can use std::mem_fun, if you dont want to use a lamda.

Are you able to do this?

std::thread myThread(std::mem_fun(&MyClass::handler),this);

std::thread accepts arguments to the function (which is the first argument) and this is passed as an argument to the mem_fun object, which then calls the handler function on this.

You could also quite simply do the below, courtesy - Start thread with member function

std::thread myThread(&MyClass::handler,this);
Community
  • 1
  • 1
Karthik T
  • 31,456
  • 5
  • 68
  • 87
5

Use lambda to access class members within a member function, you need to capture this. [this] is mandatory in below code:

void handleThings() 
{
    std::thread myThread([this]() {
        handler();
    });
}

You could capture this by reference but it's not as efficient as capturing it by value. because going through the reference requires double indirection (modulo compiler optimizations)

void handleThings() {
        std::thread myThread([&]() {
            handler();
        });
    }

Lambdas are usually a better choice than bind.

  • Easier for readers to understand.
  • More efficient.
billz
  • 44,644
  • 9
  • 83
  • 100
  • 1
    `this` is just a pointer, so passing/capturing by value is quite ok... depending on completeness of C++11 support in compiler `this->handler()` may be required to resolve ambiguity. – zaufi Jan 22 '13 at 07:23
  • How can I learn more about lambda vs. bind performance? Does this answer http://stackoverflow.com/a/8884445/711902 seem to indicate that performance is usually the same, at least with GCC 4.7? Or is the answerer talking about something else? – Trevor Dixon Jan 22 '13 at 07:53
  • I haven't test it yet, but I read from C++11 books, like `Overview of the New C++ (C++0x)` mentions that. – billz Jan 22 '13 at 07:58
  • 2
    What about `std::thread myThread(&MyClass::handler, this)` like bamboon suggested in http://stackoverflow.com/questions/10673585/start-thread-with-member-function? Is that doing the same thing as std::bind? That seems like the cleanest solution. – Trevor Dixon Jan 22 '13 at 08:06
  • @TrevorDixon, yes that works perfectly. It's very similar to `bind` and does the same thing in this case, but is not always exactly the same because the way `thread` handles its arguments doesn't support everything that `bind` supports, see http://stackoverflow.com/a/21066704/981959 for a bit more detail – Jonathan Wakely Oct 09 '14 at 10:37