6

I've a code:

class cabc{
public:
    void pr()
    {
        cout<<"abcdef";
    }
};
int main()
{

    cabc cap;
    auto f = async(cap.pr);
    f.get();
    return 0;
}

This code is not working. I know the same thing can be done using:

auto f = async(&cabc::pr,cap);

This is working. But why the first approach is not working?

5
  • 2
    Why would you expect the first approach to work? Commented Dec 3, 2013 at 8:55
  • 1
    It's not just async, it's just how the language works (or not work). Commented Dec 3, 2013 at 8:55
  • cap.pr is function like the regular one. Then why it should not work? @juanchopanza Commented Dec 3, 2013 at 8:56
  • 5
    No, cap.pr is not a function. cap.pr(arg) means something like "call cabc::pr on cap with argument arg". cap.pr by itself doesn't make sense. Commented Dec 3, 2013 at 8:57
  • 2
    It's arguable that C++ should have a concept of a "bound member function pointer" in the core language, as many people do intuitively expect that the syntax you want to use should work. However, it does not, and adding the feature to the existing type system would not be trivial. On the other hand, it is easy to emulate it on the library level -- it's called std::mem_fn and it is internally used by std::async to make the async(&a::b, c) syntax work. Commented Dec 3, 2013 at 9:51

2 Answers 2

12

cap.pr is an incomplete member function call expression. You must follow it with parentheses containing the appropriate function arguments to make a valid C++ expression.

You can't therefore pass cap.pr to std::async or any other function.

To pass a member function to std::async you need to use the syntax you found:

auto f=std::async(&capc::pr,cap);

Though in this case, you need to be aware that the cap object is copied. You could also use

auto f=std::async(&capc::pr,&cap);

to just pass a pointer to cap.

If the pointer-to-member-function syntax is unwelcome then you can use a lambda:

auto f=std::async([&]{cap.pr();});

This isn't quite the same: it doesn't pass the member function pointer and object pointer to std::async, it passes a lambda object containing a reference to cap that calls its pr member function directly. However, the result is essentially the same.

Sign up to request clarification or add additional context in comments.

1 Comment

Nifty - it didn't occur to me to use a lambda there.
1

Have a look at the function signature for async:

template< class Function, class... Args>
std::future<typename std::result_of<Function(Args...)>::type>
    async( Function&& f, Args&&... args );

(from cppreference)

It should be apparent that, firstly, whatever Function&& is, it can't be the case that cap.pr and &cabc::pr are both of that type.

More precisely, though, Function&& is supposed to be an rvalue-reference to a function pointer. &cabc::pr is just the syntax for a pointer-to-member-function, and because it's a member function, a pointer to the object itself needs to be the first argument. If cap.pr were a C-style function pointer, then your first sample might work.

Honestly, I'm not sure why your second sample works since you're not passing in a pointer to your object.

There are a number of other answers to similar questions. For example: How to, in C++11, use std::async on a member function?

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.