使用 boost::spirit::x3 v1.84 编译错误

问题描述 投票:0回答:1

请注意,此代码在 boost v1.69 的spirit x3 上编译时没有错误,该代码最初是为此开发的。该错误源自 x3::parse() 行,但由于这个模板噪音,我不知道编译器实际上想告诉我什么,也不知道为什么spirit x3 1.84有这个错误,而1.69没有。 c++17 模式下的 g++ 13.2:

#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());
      |         ~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

https://godbolt.org/z/ParTY34zf

c++ string boost-spirit string-view
1个回答
0
投票

X3的属性合成/兼容性规则一直在变化。在这个特定领域(字符串合成),我看到了一些改进,但也看到了“随机行为变化”。

这一切都很好,因为 X3 接口(仍然)被记录为“实验性”。

对属性合成有一点帮助,改变

auto const field = escaped | non_escaped;

auto const field = x3::rule<void, std::string> {} = escaped | non_escaped;

这是一个包含测试用例和许多简化/改进的演示:

住在科里鲁

#include <boost/spirit/home/x3.hpp>
namespace CsvParser {
    namespace x3           = boost::spirit::x3;
    auto const escaped     = '"' >> *(~x3::char_('"') | '"' >> x3::char_('"')) >> '"';
    auto const non_escaped = *~x3::char_(",\"\r\n");
    auto const field       = x3::rule<void, std::string> {} = escaped | non_escaped;
    auto const record      = (field % ',') >> (x3::eol | x3::eoi);
} // namespace

namespace utils {
    std::vector<std::string> parse_csv_record(std::string_view input, std::string_view& remainder) {
        std::vector<std::string> result;

        if (auto f{std::begin(input)}; parse(f, std::end(input), CsvParser::record, result))
            remainder = input.substr(std::distance(std::begin(input), f));
        else
            throw std::runtime_error{"CSV parse failure"};

        return result;
    }
} // namespace utils

#include <fmt/ranges.h>
int main() {
    std::string_view demo = R"(
foo,bar,qux
1,"some, not all, things","are",created equal,

,,
,"
'multi'
""line"" baby"
)";

    for (int lno = 1; !demo.empty(); ++lno) {
        auto v = utils::parse_csv_record(demo, demo);
        fmt::print("line #{}: {}\n", lno, v);
    }
}

打印预期内容

line #1: [""]
line #2: ["foo", "bar", "qux"]
line #3: ["1", "some, not all, things", "are", "created equal", ""]
line #4: [""]
line #5: ["", "", ""]
line #6: ["", "\n'multi'\n\"line\" baby"]

奖金

一次解析整个文件:

住在Coliru

namespace Csv {
    using Record = std::vector<std::string>;
    using File   = std::vector<Record>;
    File parse(std::string_view input) {
        File result;
        parse(std::begin(input), std::end(input), CsvParser::record % x3::eol > x3::eoi, result);
        return result;
    }
} // namespace Csv

印刷

parsed
-----
["foo", "bar", "qux"]
["1", "some, not all, things", "are", "created equal", ""]
[""]
["", "", ""]
["", "\n'multi'\n\"line\" baby"]

¹ 例如

raw[p] >> raw[p]
突然变得与
std::string
绑定属性引用兼容的情况;我不确定我是否同意

© www.soinside.com 2019 - 2024. All rights reserved.