4

If this question has been asked, I apologize.

I thought you couldn't bind functions with a different signature, but look at this:

void TakesChar(char parameter)
{
    std::cout << parameter << std::endl;
}

using CallSig = void(float);
using CallBack = std::function<CallSig>;

int main()
{
    CallBack callback = std::bind(&TakesChar, std::placeholders::_1);
    callback(1.1f);
    callback(2.2f);

    return 0;
}

That compiles and runs. You can try different parameter types and numbers. You can, for instance, modify TakesChar so that it takes no parameters, and it will still compile.

Why is this? Is there a rationale behind it? And can I enforce signatures to match exactly?

Thanks.

Kristian D'Amato
  • 3,996
  • 9
  • 45
  • 69
  • I think the signature parameter of `std::function` only concerns its own interface. The encapsulated function (object) can have any signature as long as a call is possible after conversions. Besides, one cannot possibly extract a signature from a function object with an `operator()` template. In your case, I think a `float` is just converted to `char`. – iavr Apr 30 '14 at 14:04
  • 2
    `float` is convertible to `char`. If `TakesChar`'s parameter was some type for which an implicit conversion from `float` didn't exist, your code wouldn't compile. That last part about modifying `TakesChar` so it takes no arguments is only true if you also remove `_1` from the `bind` call. You cannot bind placeholders to non-existent parameters. If you do both, then you can pass an arbitrary number of arguments to the resulting callable. The reason for that is explained in [this answer](http://stackoverflow.com/a/13252595/241631). – Praetorian Apr 30 '14 at 14:25
  • 1
    The code would be more readable with less `typedef`s, specially in a short question like this one. – David Rodríguez - dribeas Apr 30 '14 at 14:48

1 Answers1

1

Actually, there are two questions here:

  1. Why is conversion allowed ?
  2. Why if no argument is provided to bind, the return object accepts any number of argument ?

The former is just a decision on the behavior of bind: since you can call TakesChar(1.1f) why not allow std::bind(&TakesChar, _1) to bind to std::function<void(float)> ? The committee decided to allow it.

The latter, as explained in comments, was already addressed on SO. In short, not only is it easier, it also allows to bind an object that has multiple operator() of different arities.

Community
  • 1
  • 1
Matthieu M.
  • 287,565
  • 48
  • 449
  • 722