Boost.Spirit X3 v1.84编译报错,v1.69正常,求错误原因与解决
Boost.Spirit X3 CSV解析代码在1.84版本的编译错误解决方法
问题背景
基于Boost.Spirit X3编写的CSV解析代码在Boost 1.69版本可正常编译,但升级到1.84版本后,调用x3::parse()时出现编译错误。编译器提示move_to模板的参数推导冲突,Iterator被推导为char和std::string两种矛盾类型。编译环境为g++ 13.2,C++17模式。
原代码
#include <boost/spirit/home/x3.hpp> #include <algorithm> #include <iomanip> #include <iterator> #include <stdexcept> namespace x3 = boost::spirit::x3; namespace { using x3::char_; using x3::lit; using x3::no_skip; const auto escaped = lit('"') >> *((char_ - '"') | lit('"') >> char_('"')) >> lit('"'); const auto non_escaped = *(char_ - (lit(',') | lit('"') | lit('\r') | lit('\n'))); const auto field = escaped | non_escaped; const auto record = (field % ',') >> (lit("\r\n") | lit('\n') | !char_); } //namespace namespace utils { std::vector<std::string> parse_csv(std::string_view input, std::string_view& remainder) { std::vector<std::string> result; auto first { std::begin(input) }; if (!x3::parse(first, std::end(input), record, result)) { throw std::runtime_error{"CSV parse failure"}; } remainder = input.substr(std::distance(std::begin(input), first)); return result; } }
精简编译错误信息
/data3/jbuster/boost-build/install/xgcc/boost/1.84/include/boost/spirit/home/x3/support/traits/move_to.hpp:164:9: note: template argument deduction/substitution failed: /data3/jbuster/boost-build/install/xgcc/boost/1.84/include/boost/spirit/home/x3/support/traits/move_to.hpp:196:24: note: deduced conflicting types for parameter ‘Iterator’ (‘char’ and ‘std::__cxx11::basic_string<char>’) 196 | detail::move_to(src, dest, typename attribute_category<Dest>::type()); | ~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /data3/jbuster/boost-build/install/xgcc/boost/1.84/include/boost/spirit/home/x3/support/traits/move_to.hpp:168:9: note: candidate: ‘template<class Iterator, class Dest> void boost::spirit::x3::traits::detail::move_to(Iterator, Iterator, Dest&, boost::spirit::x3::traits::container_attribute)’ 168 | move_to(Iterator first, Iterator last, Dest& dest, container_attribute) | ^~~~~~~ /data3/jbuster/boost-build/install/xgcc/boost/1.84/include/boost/spirit/home/x3/support/traits/move_to.hpp:168:9: note: template argument deduction/substitution failed: /data3/jbuster/boost-build/install/xgcc/boost/1.84/include/boost/spirit/home/x3/support/traits/move_to.hpp:196:24: note: deduced conflicting types for parameter ‘Iterator’ (‘char’ and ‘std::__cxx11::basic_string<char>’) 196 | detail::move_to(src, dest, typename attribute_category<Dest>::type()); | ~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /data3/jbuster/boost-build/install/xgcc/boost/1.84/include/boost/spirit/home/x3/support/traits/move_to.hpp:180:9: note: candidate: ‘template<class Iterator, class Dest> typename boost::enable_if<boost::spirit::x3::traits::is_size_one_sequence<Dest> >::type boost::spirit::x3::traits::detail::move_to(Iterator, Iterator, Dest&, boost::spirit::x3::traits::tuple_attribute)’ 180 | move_to(Iterator first, Iterator last, Dest& dest, tuple_attribute) | ^~~~~~~ /data3/jbuster/boost-build/install/xgcc/boost/1.84/include/boost/spirit/home/x3/support/traits/move_to.hpp:180:9: note: template argument deduction/substitution failed: /data3/jbuster/boost-build/install/xgcc/boost/1.84/include/boost/spirit/home/x3/support/traits/move_to.hpp:196:24: note: deduced conflicting types for parameter ‘Iterator’ (‘char’ and ‘std::__cxx11::basic_string<char>’) 196 | detail::move_to(src, dest, typename attribute_category<Dest>::type()); | ~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /data3/jbuster/boost-build/install/xgcc/boost/1.84/include/boost/spirit/home/x3/support/traits/move_to.hpp:187:9: note: candidate: ‘template<class Iterator> void boost::spirit::x3::traits::detail::move_to(Iterator, Iterator, boost::iterator_range<T>&, boost::spirit::x3::traits::range_attribute)’ 187 | move_to(Iterator first, Iterator last, boost::iterator_range<Iterator>& rng, range_attribute) | ^~~~~~~ /data3/jbuster/boost-build/install/xgcc/boost/1.84/include/boost/spirit/home/x3/support/traits/move_to.hpp:187:9: note: template argument deduction/substitution failed: /data3/jbuster/boost-build/install/xgcc/boost/1.84/include/boost/spirit/home/x3/support/traits/move_to.hpp:196:24: note: deduced conflicting types for parameter ‘Iterator’ (‘char’ and ‘std::__cxx11::basic_string<char>’) 196 | detail::move_to(src, dest, typename attribute_category<Dest>::type()); | ~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
解决方法
问题根源是属性类型不匹配:新版本Boost.Spirit X3中,*(char_ - ...)这类解析器默认生成std::vector<char>或字符序列,但代码期望的是std::string。旧版本的隐式转换兼容在新版本中被严格的模板推导规则禁止,导致类型冲突。
修复方案:显式指定属性类型
给field解析器添加x3::as<std::string>()适配,强制解析器将匹配到的字符序列转换为std::string,确保属性类型一致。
修改后的完整代码:
#include <boost/spirit/home/x3.hpp> #include <algorithm> #include <iomanip> #include <iterator> #include <stdexcept> namespace x3 = boost::spirit::x3; namespace { using x3::char_; using x3::lit; using x3::as; const auto escaped = lit('"') >> *((char_ - '"') | lit('"') >> char_('"')) >> lit('"'); const auto non_escaped = *(char_ - (lit(',') | lit('"') | lit('\r') | lit('\n'))); const auto field = as<std::string>() [escaped | non_escaped]; const auto record = (field % ',') >> (lit("\r\n") | lit('\n') | !char_); } //namespace namespace utils { std::vector<std::string> parse_csv(std::string_view input, std::string_view& remainder) { std::vector<std::string> result; auto first { std::begin(input) }; if (!x3::parse(first, std::end(input), record, result)) { throw std::runtime_error{"CSV parse failure"}; } remainder = input.substr(std::distance(std::begin(input), first)); return result; } }
说明
添加x3::as<std::string>()后,明确告诉解析器要生成std::string类型的属性,消除了move_to模板推导时的类型矛盾,符合新版本Boost.Spirit X3的严格类型匹配要求。
内容的提问来源于stack exchange,提问作者randian
相关产品推荐
相关产品推荐

