首页 > 解决方案 > 以 size_t 为起点的 C++ 擦除向量部分

问题描述

std::vector我想i通过end. 预先计算好的ia在哪里。std::size_t

auto i = vec.size();

for (auto pos = vec.size(); pos > 0; --pos) {
  auto& elem = vec.at(pos - 1);

  if (*magic_condition*) {
    --i;
  }
}

vec.erase(vec.begin() + i, vec.end());

我收到Conversion may change the sign of the result警告

我尝试使用std::next,但仍然导致相同的警告

我发现摆脱警告但我认为非常不雅的唯一原因是

const auto begin = typename decltype(vec)::const_iterator{vec.data() + i};

vec.erase(begin, vec.end());

如果出现此警告,有什么好的解决方案可以摆脱吗?

编辑:

void update(const delta_type delta) {
  auto size = handlers.size();

  for(auto itr = handlers.rbegin(); itr != handlers.rend(); ++itr) {
    auto& handler = *itr;

    if(const auto dead = handler.update(handler, delta); dead) {
      std::swap(handler, handlers.at(--size));
    }
  }

  handlers.erase(handlers.begin() + size, handlers.end());
}

导致以下错误

../ecs/scheduler.hpp: In instantiation of ‘void sbx::scheduler<Delta>::update(sbx::scheduler<Delta>::delta_type) [with Delta = float; sbx::scheduler<Delta>::delta_type = float]’:
/home/kabelitzj/Dev/sandbox/sandbox/core/engine.cpp:39:29:   required from here
../ecs/scheduler.hpp:64:39: warning: conversion to ‘__gnu_cxx::__normal_iterator<sbx::scheduler<float>::process_handler*, std::vector<sbx::scheduler<float>::process_handler, std::allocator<sbx::scheduler<float>::process_handler> > >::difference_type’ {aka ‘long int’} from ‘long unsigned int’ may change the sign of the result [-Wsign-conversion]
   64 |     handlers.erase(handlers.begin() + size, handlers.end());
      |  

编译g++ version 9.3.0c++17

标签: c++vectoriteratortype-conversionwarnings

解决方案


显示的代码非常好,AFAICS。警告意味着vector' 的实现是错误的,而不是你。Avector::iterator可以通过索引递增,并且您的索引变量与vector用于其索引的类型相同。所以应该没有转换。但是有,因为difference_type迭代器的 与 的类型size_type不同vector

无论如何,这种代码无论如何都是不必要的。您可以通过+或在 C++20 中使用Erase-Remove 习语。那么根本不需要手动处理这些类型的循环和交换。例如:std::remove_if()vector::erase()std::erase_if()

vec.erase(
    std::remove_if(vec.begin, vec.end(),
        [](auto &elem){ return *magic_condition*; }
    ),
    vec.end()
);
std::erase_if(vec, [](auto &elem){ return *magic_condition*; });
void update(const delta_type delta) {
  handlers.erase(
    std::remove_if(handlers.begin(), handlers.end(),
      [&](auto &handler){ return (bool) handler.update(handler, delta); }
    ),
    handlers.end()
  );
}
void update(const delta_type delta) {
  std::erase_if(handlers, [&](auto &handler){ return (bool) handler.update(handler, delta); });
}

推荐阅读