Remove_if包含变体的载体



我有两个不同的对象:

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::variantstd::vector

std::vector<std::variant< TypeA, TypeB>> ab;

现在我想删除成员no = 0的所有元素。

如果没有向量仅包含TypeAstd::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将使用 TypeATypeB 实例化其模板operator()

如果要访问不同类型的"相同"数据成员,则这些类型必须是定义此数据成员的公共多态基类的子类。

但是,在您的情况下,如果TypeATypeB不相关,则必须对相应的数据成员进行类型安全访问。@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());

相关内容

  • 没有找到相关文章

最新更新