11
votes

Consider the following class:

class Foo
{
   private:
      void bar(const size_t);
   public:
      void foo();
};

now Foo::foo() should start threads executing bar, so this is how it's implemented:

void Foo:foo()
{
    auto handle = std::async(std::launch::async, &Foo::bar, this, 0);
    handle.get();
}

This works flawlessly with g++-4.6.3, but not with g++-4.5.2, the error message is

include/c++/4.5.2/functional:180:9: Error: must use ».« or »->« to call pointer-to-member function in »std::declval with _Tp = void (Foo::*)(long unsigned int), typename std::add_rvalue_reference<_Tp>::type = void (Foo::&&)(long unsigned int) (...)«, e.g. »(... -> std::declval with _Tp = void (Foo::*)(long unsigned int), typename std::add_rvalue_reference<_Tp>::type = void (Foo::*&&)(long unsigned int)) (...)«

So obviously the error lies within the old version of g++. It is possible to work around this issue by making the method public and introducing the following helper function:

void barHelp(Foo* foo, const size_t n)
{
    foo->bar(n);
}
void Foo:foo()
{
    auto handle = std::async(std::launch::async, barHelp, this, 0);
    handle.get();
}

However, making a method public isn't the best design decision. Is there another way to work around this issue without changing the compiler and leaving the method private?

2

2 Answers

13
votes

The problem appears to be that it won't play nice with member functions. Perhaps you can std::bind the member function to your object first, before passing it to std::async:

auto func = std::bind(&Foo::bar, this, std::placeholders::_1);
auto handle = std::async(std::launch::async, func, 0);
4
votes

I would prefer lambdas to std::bind

#include <iostream>
#include <future>

class Foo
{
private:
    void bar(const size_t)
    {}
public:
    void foo()
    {
        auto handle = std::async(std::launch::async, [this](){
            this->bar(0);
        });
        handle.get();
    }
};

int main()
{
    Foo foo;
    foo.foo();
    return 0;
}

or, but less readable to me,

        auto handle = std::async(std::launch::async, [this](const size_t num){
            this->bar(num);
        }, 0);