Подтвердить что ты не робот

Вывод аргумента шаблона из подписи вызова std:: function

Рассмотрим эту функцию шаблона:

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

Почему компилятор не может вывести ReturnT из прошедшей сигнатуры вызова?

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

foo<bool>(bar); // works
foo(bar); // error: no matching function call
4b9b3361

Ответ 1

std::function<bool()> bar;

foo(bar); // works just fine

С++ не может выводить возвращаемый тип из вашей функции bar, потому что он должен был знать тип, прежде чем он сможет найти все конструкторы, которые берут ваш указатель на функцию.

Например, кто скажет, что std::function<std::string()> не имеет конструктора, берущего bool (*)()?

Ответ 2

Указатель функции типа bool (*)() может быть преобразован в std::function<bool()>, но не является одним и тем же типом, поэтому требуется преобразование. Прежде чем компилятор сможет проверить, возможно ли это преобразование, необходимо вывести ReturnT как bool, но для этого ему нужно уже знать, что std::function<bool()> является возможным преобразованием, которое невозможно, пока оно не выводит ReturnT... увидеть проблему?

Кроме того, считайте, что bool(*)() можно также преобразовать в std::function<void()> или std::function<int()>..., который должен быть выведен?

Рассмотрим это упрощение:

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

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

int main()
{
    foo(1);
}

Как компилятор может знать, хотите ли вы создать function<int> или function<char> или function<void>, когда все они могут быть построены с помощью int?

Ответ 3

Функция bar имеет тип bool (*)() или так, то есть: обычный тип функции pre-С++ 11. Я не уверен в С++ 11, но я думаю, что компилятор не видит связи между bool (*)() и const std::function<ReturnT()>&, даже если первый может быть неявно преобразован во второй для ReturnT = bool.