Как std:: function<std:: option <T>()> совместима с лямбда-кодом, возвращающим T?
Я могу создать std::function
это возвращает std::optional<Foo>
и назначил лямбду, которая возвращает Foo
к этому. Может кто-нибудь подробно объяснить, как это возможно?
простой пример:
#include <iostream>
#include <optional>
#include <functional>
int main()
{
int k = 13;
std::function<std::optional<int>()> f1;
f1 = [&] {return k++;}; //implicite int
std::cout<<"k = " << f1().value() << std::endl;
f1 = [&] () -> int {return k;}; //explicite int
std::cout<<"k = " << f1().value() << std::endl;
}
3 ответа
Конструкторstd::optional
(#8 в наборе перегрузки) является условно явным, в зависимости от параметра шаблона. В твоем случае (std::optional<int>
), вы можете неявно создавать экземпляры,
std::optional<int> opt;
opt = 42; /* No problem, implicit construction. */
и это именно то, что обертка std::function<std::optional<int>>
делает. Вызывает упакованную функцию, которая возвращает int
и использует это возвращаемое значение, чтобы неявно построить свое собственное возвращаемое значение, std::optional<int>
,
Существует неявное преобразование из int
в std::optional<int>
,
Конструктор шаблона std::function
использует названное требование Callable, которое требует только, чтобы INVOKE
Выражение должно быть неявно преобразовано в тип результата, а не в то, что они одного типа.
Короче говоря, цель, назначенная std::function
должен быть Callable для параметров и тип возвращаемого параметра шаблона std::function
,
Например, учитывая:
std::function<R(P1, P2)>
p1
типаP1
p2
типаP2
Вы можете назначить цель f
к нему, если f(p1, p2)
хорошо сформирован и неявно преобразуется в R
, (*)
Другие ответы показывают, что std::optional<int>
неявно стягиваемый из int
,
Так в вашем примере [&] () -> int {return k;}()
возвращает int
и это неявно конвертируется в std::optional<int>
,
(*) Обратите внимание, что это немного упрощено, так как строгое определение включает функцию / концепцию вызова