Ubuntu升级至24.04后Boost::split编译失败问题咨询
原本可正常运行的代码:
vector<string> mylist = ...; for (vector<string>::const_iterator it = mylist.begin(); it != mylist.end(); ++it) { vector<string> listitem_details; boost::split(listitem_details, *it, boost::is_any_of(",")); ... }
这段代码在Ubuntu 22.04上能正常编译运行,但升级到Ubuntu 24.04后编译失败,报错信息如下:
project/include/boost/concept/detail/has_constraints.hpp:32:62: required by substitution of ‘template<class Model> boost::concepts::detail::yes boost::concepts::detail::has_constraints_(Model*, boost::concepts::detail::wrap_constraints<Model, (& Model::constraints)>*) [with Model = boost::SinglePassRangeConcept<const boost::iterator_range<__gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> > > >]’ project/include/boost/concept/detail/has_constraints.hpp:42:5: required from ‘const bool boost::concepts::not_satisfied<boost::SinglePassRangeConcept<const boost::iterator_range<__gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> > > > >::value’ project/include/boost/concept/detail/has_constraints.hpp:45:51: required from ‘struct boost::concepts::not_satisfied<boost::SinglePassRangeConcept<const boost::iterator_range<__gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> > > > >’ project/include/boost/concept/detail/general.hpp:51:8: [ skipping 8 instantiation contexts, use -ftemplate-backtrace-limit=0 to disable ] project/include/boost/iterator/iterator_facade.hpp:901:3: required from ‘typename boost::iterators::detail::enable_if_interoperable<Derived1, Derived2, typename boost::mpl::apply2<boost::iterators::detail::always_bool2, Derived1, Derived2>::type>::type boost::iterators::operator!=(const boost::iterators::iterator_facade<Derived1, V1, TC1, Reference1, Difference1>&, const boost::iterators::iterator_facade<Derived2, V2, TC2, Reference2, Difference2>&) [with Derived1 = boost::iterators::transform_iterator<boost::algorithm::detail::copy_iterator_rangeF<std::__cxx11::basic_string<char>, __gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> > >, boost::algorithm::split_iterator<__gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> > >, boost::use_default, boost::use_default>; V1 = std::__cxx11::basic_string<char>; TC1 = boost::iterators::forward_traversal_tag; Reference1 = std::__cxx11::basic_string<char>; Difference1 = long int; Derived2 = boost::iterators::transform_iterator<boost::algorithm::detail::copy_iterator_rangeF<std::__cxx11::basic_string<char>, __gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> > >, boost::algorithm::split_iterator<__gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> > >, boost::use_default, boost::use_default>; V2 = std::__cxx11::basic_string<char>; TC2 = boost::iterators::forward_traversal_tag; Reference2 = std::__cxx11::basic_string<char>; Difference2 = long int; typename boost::iterators::detail::enable_if_interoperable<Derived1, Derived2, typename boost::mpl::apply2<boost::iterators::detail::always_bool2, Derived1, Derived2>::type>::type = bool; typename boost::mpl::apply2<boost::iterators::detail::always_bool2, Derived1, Derived2>::type = bool]’ /usr/aarch64-linux-gnu/include/c++/11/bits/stl_vector.h:1562:21: required from ‘void std::vector<_Tp, _Alloc>::_M_range_initialize(_InputIterator, _InputIterator, std::input_iterator_tag) [with _InputIterator = boost::iterators::transform_iterator<boost::algorithm::detail::copy_iterator_rangeF<std::__cxx11::basic_string<char>, __gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> > >, boost::algorithm::split_iterator<__gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> > >, boost::use_default, boost::use_default>; _Tp = std::__cxx11::basic_string<char>; _Alloc = std::allocator<std::__cxx11::basic_string<char> >]’ /usr/aarch64-linux-gnu/include/c++/11/bits/stl_vector.h:657:23: required from ‘std::vector<_Tp, _Alloc>::vector(_InputIterator, _InputIterator, const allocator_type&) [with _InputIterator = boost::iterators::transform_iterator<boost::algorithm::detail::copy_iterator_rangeF<std::__cxx11::basic_string<char>, __gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> > >, boost::algorithm::split_iterator<__gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> > >, boost::use_default, boost::use_default>; <template-parameter-2-2> = void; _Tp = std::__cxx11::basic_string<char>; _Alloc = std::allocator<std::__cxx11::basic_string<char> >; std::vector<_Tp, _Alloc>::allocator_type = std::allocator<std::__cxx11::basic_string<char> >]’ project/include/boost/algorithm/string/iter_find.hpp:186:31: required from ‘SequenceSequenceT& boost::algorithm::iter_split(SequenceSequenceT&, RangeT&&, FinderT) [with SequenceSequenceT = std::vector<std::__cxx11::basic_string<char> >; RangeT = const std::__cxx11::basic_string<char>&; FinderT = boost::algorithm::detail::token_finderF<boost::algorithm::detail::is_any_ofF<char> >]’ project/include/boost/algorithm/string/split.hpp:158:50: required from ‘SequenceSequenceT& boost::algorithm::split(SequenceSequenceT&, RangeT&&, PredicateT, boost::algorithm::token_compress_mode_type) [with SequenceSequenceT = std::vector<std::__cxx11::basic_string<char> >; RangeT = const std::__cxx11::basic_string<char>&; PredicateT = boost::algorithm::detail::is_any_ofF<char>]’ project/src/sample.cpp:427:15: required from here
注:sample.cpp:427即为上述代码中的boost::split行。系统升级过程中未修改Boost库,仅更新了编译器及libc、libm、libstdc++等系统库。
核心原因
Ubuntu 24.04默认使用GCC 13,该版本对C++模板的约束检查更严格。你所用的旧版Boost库(如1.74及更早)的split函数内部迭代器实现,与GCC 13的标准库迭代器兼容性出现问题,具体表现为Boost Concepts对SinglePassRangeConcept的验证失败,触发模板实例化错误。
解决方法
升级Boost库到兼容版本
旧版Boost在GCC 13下存在此类适配问题,升级到Boost 1.81及以上版本即可修复,新版本已针对GCC 13调整了相关实现。临时 workaround:转换为非const字符串引用
若暂时无法升级Boost,可修改boost::split调用,将*it转换为非const引用避开const迭代器的概念检查:boost::split(listitem_details, const_cast<std::string&>(*it), boost::is_any_of(","));注意:此方法仅为临时方案,
const_cast存在潜在风险,若*it实际是不可修改的左值,后续修改会导致未定义行为,优先推荐升级Boost。调整编译选项(不推荐长期使用)
可尝试添加编译宏-DBOOST_ALLOW_DEPRECATED_HEADERS,或禁用Boost Concepts的严格检查,但可能引入其他兼容性问题,不建议作为长期解决方案。
内容的提问来源于stack exchange,提问作者Daniel

