std::u32string::erase编译报错,如何适配GCC使其正常运行?
GCC 9.4.0下std::u32string移除字符代码编译报错的解决
问题描述
我需要从std::u32string中移除指定字符,例如移除字符串U"abd|def"中的'|',编写的代码如下:
#include <string> int main() { std::u32string a = U"abd|def"; a.erase(std::remove(a.begin(), a.end(), U'|'), a.end()); }
该代码在MacBook的Apple clang 14.0.0环境下可正常编译运行,但在Ubuntu系统的GCC 9.4.0编译时出现错误,错误信息为:
no instance of overloaded function "std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::erase [with _CharT=char32_t, _Traits=std::char_traits<char32_t>, _Alloc=std::allocator<char32_t>]" matches the argument listC/C++(304) m.cpp(6, 7): argument types are: (int, __gnu_cxx::__normal_iterator<char32_t *, std::__cxx11::basic_string<char32_t, std::char_traits<char32_t>, std::allocator<char32_t>>>) m.cpp(6, 7): object type is: std::u32string
请问如何修改代码,使其在GCC环境下也能正常编译运行?
解决方法
问题根源是GCC 9.4.0对std::basic_string<char32_t>::erase的实现限制:旧版本GCC中,这个erase函数的重载不支持直接接收std::remove返回的迭代器作为第一个参数(编译器误将迭代器解析为整数类型的位置参数),但它支持传入两个迭代器构成的范围来删除元素。
可以通过以下两种方式修改:
方式一:显式处理迭代器范围(兼容C++11及以上)
先将std::remove的返回值保存为迭代器,再把这个迭代器和字符串末尾迭代器一起传给erase,同时必须显式包含<algorithm>头文件(std::remove的定义所在):
#include <string> #include <algorithm> int main() { std::u32string a = U"abd|def"; auto new_end = std::remove(a.begin(), a.end(), U'|'); a.erase(new_end, a.end()); }
方式二:使用C++20的std::erase_if(需升级编译器)
如果可以将GCC版本升级到11及以上(支持C++20),可以使用更简洁的std::erase_if,无需手动处理迭代器:
#include <string> #include <algorithm> int main() { std::u32string a = U"abd|def"; std::erase_if(a, [](char32_t c) { return c == U'|'; }); }
内容的提问来源于stack exchange,提问作者Haohan Yang
相关产品推荐
相关产品推荐

