0

This doesn't work: http://ideone.com/mUL5Y

Figured I helped it a little with deducting that type: http://ideone.com/mGfUj

Doesn't work either! I don't understand why not.

How should I do this?

Nick
  • 2,662
  • 2
  • 25
  • 48
  • You couldn't just copy the code into the post? You're making us look at an off-site source for a 24-line piece of code? – Nicol Bolas Mar 14 '12 at 03:40
  • @NicolBolas Yes. You get the errors, can clone it, player around with it a bit... it's considered proper netiquette on irc://chat.freenode.net/##c++ and I figured it was convenient here too. – Nick Mar 14 '12 at 13:05

1 Answers1

1

The problem seems to be that std::bind is internally passing the evaluated results of the Callable (it's actually a std::bind<> type) object c when you pass it for a second time here:

part2(std::bind(&Quux::part3<Callable>, this, 3, c))

It's not passing an un-evaluated version of the std::bind object like you're assuming.

Therefore since your f function returns a void type, the result of the c expression is internally passed as a void type, and not an un-evaluated callable function object. Thus when you attempt to call the Callable object c in Quux::part2, which in-turn attempts to evaluate the call c in Quux::part3, it cannot pass a callable object as the second argument to Quux::part3, since the type it is passing is actually a void type, and not a callable type.

For further reference, see here: http://en.cppreference.com/w/cpp/utility/functional/bind

Note particularly that:

If std::is_bind_expression<T>::value==true (i.e., another std::bind() subexpression was used as an argument in the initial call to bind), then that bind-subexpression is invoked immediately and its result is passed to the function.

If you want to delay the evaluation so that it happens when you want it to, and not when you pass a std::bind sub-expression, you will have to look for another method, such as a lambda, or std::function<> object, a functor, or some other class object type that is both callable and can store a state which can be evaluated later.

Jason
  • 31,834
  • 7
  • 59
  • 78
  • How can it be evaluated? c isn't called anywhere... why does it turn from void() to void? – Nick Mar 14 '12 at 13:06
  • 1
    When you pass a `std::bind` to another `std::bind`, the first sub-expression is evaluated, and the *results* are passed to the second `std::bind` ... so if you evaluate a `void (*)(int)`, you're going to end up with a `void` type as the result, not a callable `void(*)(int)`. Although you are not explicitly calling `c`, it is in fact being called behind the scenes because of the nested `std::bind` expressions, with the result of the call being passed on, not the callable object itself. – Jason Mar 14 '12 at 16:29
  • BTW, I think you'll get a better idea of where and how this transformation takes place if you use normal free-standing functions rather than class methods. [Here is an example with the associated error messages](http://ideone.com/CCQot) – Jason Mar 14 '12 at 16:38
  • Question remains: Why? This doesn't seem to make a lot of sense to me. – Nick Mar 15 '12 at 13:19