Вывести аргумент шаблона из сигнатуры вызова 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

3 ответа

Решение
std::function<bool()> bar;

foo(bar); // works just fine

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

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

Указатель на функцию типа 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?

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

Другие вопросы по тегам