【问题标题】:Remove_if with vector containing variants带有包含变体的向量的 Remove_if
【发布时间】:2019-01-31 21:12:16
【问题描述】:

我有两个不同的对象:

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::vectorstd::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 的谓词中添加它,或者我可以吗?

【问题讨论】:

    标签: c++ c++17 variant


    【解决方案1】:

    是的,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&lt;TypeA, TypeB&gt;&amp;,而 auto 比输入 std::variant&lt;TypeA, TypeB&gt; 更方便。但是对于内部 lambda,重要的是 lambda 是通用的,因为 visit 将使用 TypeATypeB 实例化其模板 operator()

    【讨论】:

      【解决方案2】:

      如果您想访问不同类型的“相同”数据成员,那么这些类型需要是定义该数据成员的通用多态基类的子类。

      但是,在您的情况下,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());
      

      【讨论】:

      • 这是自找麻烦。当您向变体添加第三种类型时会发生什么?你还记得你需要更新这个吗?如果您碰巧正在寻找的类型不是复制成本低怎么办?还是完全可以复制?还是默认可构造?
      猜你喜欢
      • 2019-03-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-03-07
      • 2018-12-29
      • 1970-01-01
      • 2018-06-07
      相关资源
      最近更新 更多