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