我有两个不同的对象:
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::vector
一起存储在std::variant
中
std::vector<std::variant< TypeA, TypeB>> ab;
现在,我要删除所有元素均为成员no = 0
。
在没有std::variant
且向量仅包含TypeA
的情况下,我会这样做:
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
的谓词中刊登广告,还是可以吗?
答案 0 :(得分:10)
是的,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
将同时使用operator()
和TypeA
实例化其模板TypeB
。
答案 1 :(得分:3)
如果要访问不同类型的“相同”数据成员,则这些类型需要是定义此数据成员的通用多态基类的子类。
但是,在您的情况下,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());