Remove_if 向量包含变体
Remove_if with vector containing variants
我有两个不同的对象:
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
的谓词中添加它,或者我可以吗?
是的,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()
如果要访问不同类型的 "same" 数据成员,则这些类型需要是定义此数据成员的公共多态基 class 的子class。
但是,在您的情况下,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());
我有两个不同的对象:
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
的谓词中添加它,或者我可以吗?
是的,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()
如果要访问不同类型的 "same" 数据成员,则这些类型需要是定义此数据成员的公共多态基 class 的子class。
但是,在您的情况下,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());