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