erase-remove 成语:我刚刚删除了什么吗?

erase-remove idiom: did I just delete something?

我正在使用擦除-删除习惯用法:

template <typename T>
bool garbageCollectVector(std::vector<T>& v) {
    // Use the erase-remove idiom in combination with a lambda expression
    v.erase(
        std::remove_if(v.begin(), v.end(),
            [this](const T& elem) -> bool {
                return this->shouldRemove(elem);
            }
        ),
        v.end());
    return /* what to return? */;
}

并想 return 该方法是否实际删除了任何元素。 最干净的方法是什么?

我只是检查向量的大小。类似于:

auto size_before = v.size();
// v.erase( ... )
return v.size() != size_before;

除了大小检查,您还可以拆分实施:

template <typename T>
bool garbageCollectVector(std::vector<T>& v) {
    // Use the erase-remove idiom in combination with a lambda expression
    auto it = std::remove_if(v.begin(), v.end(),
                             [this](const T& elem) -> bool {
                                return this->shouldRemove(elem);
                             });
    if (it == v.end()) {
        return false;
    } else {
        v.erase(it, v.end());
        return true;
    }
}

怎么样:

template <typename T>
bool garbageCollectVector(std::vector<T>& v) {
    auto prevSize = v.size();
    // Use the erase-remove idiom in combination with a lambda expression
    v.erase(
        std::remove_if(v.begin(), v.end(),
            [this](const T& elem) -> bool {
                return this->shouldRemove(elem);
            }
        ),
        v.end());
    return !(prevSize == v.size());
}

其他人提出了更好的替代方案,但为了完整起见,让我补充一下。它使用一个标志来检查谓词是否曾返回 true。

template <typename T>
bool garbageCollectVector(std::vector<T>& v) {
    // Use the erase-remove idiom in combination with a lambda expression
    bool removed = false;
    v.erase(
        std::remove_if(v.begin(), v.end(),
            [this,&removed](const T& elem) -> bool {
                bool to_remove = this->shouldRemove(elem);
                removed = removed || to_remove;
                return to_remove;
            }
        ),
        v.end());
    return removed;
}
template<class C, class F>
bool erase_remove_if(C&c,F&&f){
  using std::begin; using std::end;
  auto it=std::remove_if(begin(c),end(c),std::forward<F>(f));
  if (it==end(c)) return false;
  c.erase(it, end(c));
  return true;
}

这将成语放入函数中。

template <typename T>
bool garbageCollectVector(std::vector<T>& v) {
  // Use the erase-remove idiom in combination with a lambda expression
  return erase_remove_if(v,
    [this](const T& elem) -> bool {
      return this->shouldRemove(elem);
    }
  );
}

这使每行的复杂性保持理智。

您可以调整哪个(跟踪 bool 或迭代器检查)更快,如果您发现对性能有影响,可以在任何地方更改 erase_remove_if