Reputation: 305
#include <iostream>
#include <vector>
#include <variant>
template<class... Ts> struct overload : Ts... { using Ts::operator()...; };
template<class... Ts> overload(Ts...) -> overload<Ts...>;
class data_output
{
public:
double create_data() { return 1.57;}
};
class data_output_two
{
public:
int create_data() { return 66;}
};
int main()
{
using my_type = std::variant<data_output, data_output_two>;
std::vector<my_type> data_vec;
auto my_lambda = overload{[](data_output& d) {return d.create_data();},
[](data_output_two& d) {return d.create_data();}};
data_vec.emplace_back(data_output{});
data_vec.emplace_back(data_output_two{});
std::cout << std::visit(my_lambda, data_vec[0]) << "\n";
}
With this I get the error
/usr/include/c++/8.2.1/variant:836:43: error:
invalid conversion from ‘std::__success_type<int>::type (*)(overload<main()::<lambda(data_output&)>, main()::<lambda(data_output_two&)> >&, std::variant<data_output, data_output_two>&)’
{aka ‘int (*)(overload<main()::<lambda(data_output&)>, main()::<lambda(data_output_two&)> >&, std::variant<data_output, data_output_two>&)’}
to ‘double (*)(overload<main()::<lambda(data_output&)>, main()::<lambda(data_output_two&)> >&, std::variant<data_output, data_output_two>&)’ [-fpermissive]
{ return _Array_type{&__visit_invoke}; }
If I try return an int
from both data_output
and data_output_two
it compiles fine. What am I overlooking here?
Here is a link to a godbolt
Edit:
I would like to get able to do std::visit(gen_visit, vec[0])
and get a double and then possibly do a std::visit(get_visit, vec[1])
and get a int. Is that possible?
Upvotes: 0
Views: 131
Reputation: 275976
Visit returns a single type.
Your code is asking it to return two different types.
It cannot do that.
Now, the single type it returns could be in turn a variant over two types. But tht mostly kicks the can down the road.
{[](data_output& d)->std::variant<int,double> {return d.create_data();},
[](data_output_two& d)->std::variant<int, double> {return d.create_data();}};
with this you'll have to revisit in order to print:
std::visit( [](auto&&x){std::cout << x << "\n";}, std::visit(my_lambda, data_vec[0]) );
Now you can write some metaprogramming to deduce the proper return type of the composit overload/visit.
But more practically simply do the processing in the first visit:
std::visit([&](auto&&x){ std::cout<<my_lambda(x)<<"\n";}, data_vec[0] );
Upvotes: 4