我有两个不同的对象:
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;
};
它们存储在带有std::variant
的std::vector
中
std::vector<std::variant< TypeA, TypeB>> ab;
现在我想删除成员no = 0
的所有元素。
如果没有向量仅包含TypeA
的std::variant
,我会这样做:
ab.erase(std::remove_if(ab.begin(), ab.end(),
[](const TypeA& a) { return a.no == 0; }), ab.end());
但是如何合并std::variant
?我试图用std::visit
想出一些东西,但我不能在std::remove_if
的谓词中做广告,或者我可以吗?
是的,std::visit
可以提供帮助。 传递给visit
的函子只需要能够接受每种类型的variant
,最简单的方法是使用泛型 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());
这里 外 lambda 的v
类型始终用作const std::variant<TypeA, TypeB>&
,auto
比键入 std::variant<TypeA, TypeB>
更方便。 但是对于内部 lambda,重要的是 lambda 是通用的,因为visit
将使用 TypeA
和 TypeB
实例化其模板operator()
。
如果要访问不同类型的"相同"数据成员,则这些类型必须是定义此数据成员的公共多态基类的子类。
但是,在您的情况下,如果TypeA
和TypeB
不相关,则必须对相应的数据成员进行类型安全访问。@aschepler提供的解决方案使用std::visit
函子以通用方式显示了这一点;以下解决方案没有std::visit
(因此不是那么优雅,但仍然有效):
ab.erase(std::remove_if(ab.begin(), ab.end(),
[](const std::variant< TypeA, TypeB>& v) {
int no;
if (v.index()==0) {
no = std::get<0>(v).no;
} else {
no = std::get<1>(v).no;
}
return no==0;
}), ab.end());