13

Consider this template function:

template<typename ReturnT>
ReturnT foo(const std::function<ReturnT ()>& fun)
{
    return fun();
}

Why isn't it possible for the compiler to deduce ReturnT from the passed call signature?

bool bar() { /* ... */ }

foo<bool>(bar); // works
foo(bar); // error: no matching function call
Deduplicator
  • 44,692
  • 7
  • 66
  • 118
Karl von Moor
  • 8,484
  • 4
  • 40
  • 52
  • 1
    An answer to [one of my previous questions](http://stackoverflow.com/questions/9625526/check-at-compile-time-if-template-argument-is-void) allows this sort of syntax. I hope that helps. It's specialized in case the return type is void too. – chris Jun 19 '12 at 14:47
  • @chris Thanks for the hint - I'll try to understand it :) – Karl von Moor Jun 19 '12 at 14:51
  • N.B. very similar to http://stackoverflow.com/q/7608741/981959 and http://stackoverflow.com/q/9242234/981959, but I think the answers here are clearer for this specific question. – Jonathan Wakely Jun 19 '12 at 16:02

3 Answers3

17

A function pointer of type bool (*)() can be converted to std::function<bool()> but is not the same type, so a conversion is needed. Before the compiler can check whether that conversion is possible it needs to deduce ReturnT as bool, but to do that it needs to already know that std::function<bool()> is a possible conversion, which isn't possible until it deduces ReturnT ... see the problem?

Also, consider that bool(*)() could also be converted to std::function<void()> or std::function<int()> ... which should be deduced?

Consider this simplification:

template<typename T>
  struct function
  {
    template<typename U>
      function(U) { }
  };

template<typename T>
  void foo(function<T>)
  { }

int main()
{
    foo(1);
}

How can the compiler know whether you wanted to create function<int> or function<char> or function<void> when they can all be constructed from an int?

Jonathan Wakely
  • 166,810
  • 27
  • 341
  • 521
8
std::function<bool()> bar;

foo(bar); // works just fine

C++ can't deduce the return type from your function bar because it would have to know the type before it could find all the constructors that take your function pointer.

For example, who's to say that std::function<std::string()> doesn't have a constructor taking a bool (*)()?

bames53
  • 86,085
  • 15
  • 179
  • 244
1

The function bar is of type bool (*)() or so, that is: a normal pre-C++11 function type. I'm not that confident in C++11, but I guess the compiler does not see the connection between bool (*)() and const std::function<ReturnT()>&, even when the first can be implicitly converted into the second for ReturnT = bool.

Stefan Majewsky
  • 5,427
  • 2
  • 28
  • 51
  • Actually, no matter how the conversion proceeds, the definition of std::function is: `template class function` where `R` is known to be `bool` … therefore `ReturnT` should be deducable for `foo`, right? – Karl von Moor Jun 19 '12 at 14:56
  • @Karl, but `std::function` has a constructor taking _any_ type, so `bool(*)()` could also be converted to `std::function` or other types - there isn't a single, unique conversion sequence that means only a single `std::function` specialization can be deduced – Jonathan Wakely Jun 19 '12 at 15:07
  • @JonathanWakely Okay, think I see it now. Thanks for helping :-) – Karl von Moor Jun 19 '12 at 15:12