I want to erase a section of a std::vector
e.g i
th element through end
. Where i
is a std::size_t
that is calculated beforehand.
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());
I get a Conversion may change the sign of the result
warning
I tried using std::next
but that still results in the same warning
The only why I found that gets rid of the warning, but I think is very unelegant is
const auto begin = typename decltype(vec)::const_iterator{vec.data() i};
vec.erase(begin, vec.end());
Is there any good solution to get rid if this warning?
EDIT:
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());
}
Results in following error
../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());
|
Compiled with g version 9.3.0
and c 17
CodePudding user response:
The code shown is perfectly fine, AFAICS. The warning implies that the vector
's implementation is in the wrong, not you. A vector::iterator
can be incremented by an index, and your index variable is the same type that vector
uses for its indexes. So there should be no conversion. But there is, because the difference_type
of the iterator is not the same type as the size_type
of the vector
.
In any case, this kind of code is unnecessary anyway. You could just use the Erase-Remove idiom via std::remove_if()
vector::erase()
, or std::erase_if()
in C 20. Then there would be no need to handle these kinds of loops and swaps manually at all. For example:
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); });
}