C++ 以 size_t 作为起点擦除向量部分
C++ erasing section of vector with a size_t as start point
我想擦除 std::vector
的一部分,例如 i
到 end
的元素。其中 i
是预先计算的 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.0
和 c++17
编译
显示的代码非常好,AFAICS。警告暗示 vector
的实现是错误的,而不是你。 vector::iterator
可以通过索引递增,并且您的索引变量与 vector
用于其索引的类型相同。所以应该没有转换。但是有,因为迭代器的difference_type
和vector
的size_type
不是同一个类型。
不管怎样,这种代码反正是没有必要的。您可以只使用 C++20 中的 Erase-Remove idiom via std::remove_if()
+vector::erase()
, or 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); });
}
我想擦除 std::vector
的一部分,例如 i
到 end
的元素。其中 i
是预先计算的 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.0
和 c++17
显示的代码非常好,AFAICS。警告暗示 vector
的实现是错误的,而不是你。 vector::iterator
可以通过索引递增,并且您的索引变量与 vector
用于其索引的类型相同。所以应该没有转换。但是有,因为迭代器的difference_type
和vector
的size_type
不是同一个类型。
不管怎样,这种代码反正是没有必要的。您可以只使用 C++20 中的 Erase-Remove idiom via std::remove_if()
+vector::erase()
, or 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); });
}