I am trying to std::visit
a std::variant
of std::function
types.
Why does the following code not compile:
#include <functional>
#include <variant>
int main()
{
std::variant<
std::function< int () >,
std::function< float () >
> func_variant {std::in_place_index<0>, [] () { return 42; }};
auto object = std::visit( [] (auto& func) { return func(); }, func_variant);
return 0;
}
The error happens in the call of std::visit
, where it says:
error: invalid conversion from ‘std::__success_type<float>::type (*)(main()::<lambda(auto:1&)>&&, std::variant<std::function<int()>, std::function<float()> >&)’ {aka ‘float (*)(main()::<lambda(auto:1&)>&&, std::variant<std::function<int()>, std::function<float()> >&)’} to ‘int (*)(main()::<lambda(auto:1&)>&&, std::variant<std::function<int()>, std::function<float()> >&)’ [-fpermissive]
{ return _Array_type{&__visit_invoke}; }
^
Each of your std::function
types returns a different type, so the return type of the lambda you are passing to std::visit
depends on the type of the selected element of the lambda. This means that the auto-type-deduction can't work, as the call to std::visit
must have a single return type which is independent of which element of the variant is active.
You could make a return type variant: using returns=std::variant<int,float>
and then cast the return in your lambda to that:
using returns=std::variant<int,float>;
auto object = std::visit( [] (auto& func) { return returns(func()); }, func_variant);
That way the return type of your lambda is the same in all cases, but you will then need to query the result to see what you got.