使用size_t删除std::vector区间触发符号转换警告的解决办法
问题原因
警告的根本原因是:std::vector随机访问迭代器的operator+要求传入的参数是有符号的difference_type(通常为ptrdiff_t),而你传入的size是无符号的std::size_t类型,开启-Wsign-conversion编译选项时就会触发签名转换警告。
推荐解决方案
方案1:改用标准擦除移除 idiom(最优,完全规避偏移计算)
你当前的业务逻辑是将标记为dead的处理器移到容器末尾再批量删除,属于典型的移除元素场景,直接用标准库算法即可,完全不需要手动维护偏移量,代码更简洁也不会触发警告:
void update(const delta_type delta) { // 不稳定移除,和你现有swap实现逻辑一致,性能更高 auto new_end = std::remove_if(handlers.begin(), handlers.end(), [delta](auto& handler) { return handler.update(handler, delta); }); handlers.erase(new_end, handlers.end()); }
如果你需要保留存活处理器的相对顺序,把std::remove_if换成std::stable_partition即可。
方案2:显式转换偏移量类型
如果你不想改动现有逻辑,只需要将无符号的size显式转换为迭代器对应的有符号difference_type即可,写法清晰也能消除警告:
handlers.erase(std::next(handlers.begin(), static_cast<typename decltype(handlers)::difference_type>(size)), handlers.end());
C++20及以上版本可以直接用更简洁的std::iter_difference_t:
handlers.erase(std::next(handlers.begin(), static_cast<std::iter_difference_t<decltype(handlers)>>(size)), handlers.end());
方案3:调整偏移量变量类型
因为size的取值范围永远不会超过vector的最大长度,而vector的最大长度必然在ptrdiff_t的取值范围内(否则operator[]的偏移本身就会溢出),所以你可以直接把size变量定义为ptrdiff_t类型,从根源避免转换:
void update(const delta_type delta) { auto size = static_cast<ptrdiff_t>(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()); }
内容的提问来源于stack exchange,提问作者Symlink
相关产品推荐
相关产品推荐

