I have two different objects:
struct TypeA {
std::size_t no;
std::string data;
std::string data2;
};
struct TypeB {
std::size_t no;
std::string data;
std::string data2;
std::string data3;
};
They are stored in a std::vector
with std::variant
std::vector<std::variant< TypeA, TypeB>> ab;
Now i want to remove all elements were the member no = 0
.
Without the std::variant
with the vector containing only TypeA
I would do it like this:
ab.erase(std::remove_if(ab.begin(), ab.end(),
[](const TypeA& a) { return a.no == 0; }), ab.end());
But how to incorporate the std::variant
? I tried to come up with something with std::visit
but i cannot ad it in the predicate of std::remove_if
or can I?
Yes, std::visit
can help. The functor passed to visit
just needs to be able to accept each type of the variant
, and the easiest way to do that is with a generic lambda:
ab.erase(
std::remove_if(
ab.begin(),
ab.end(),
[](const auto &v) {
return std::visit(
[](const auto &obj) { return obj.no == 0; },
v);
}),
ab.end());
Here the type of v
for the outer lambda is always used as const std::variant<TypeA, TypeB>&
, and auto
is just more convenient than typing out std::variant<TypeA, TypeB>
. But for the inner lambda, it's important that the lambda is generic, because visit
will instantiate its template operator()
with both TypeA
and TypeB
.