boost.spirit 编译错误:无法将参数 1 从"const char *"转换为"std::_String_iterator<std::_String_val>
boost.spirit compilation error : cannot convert argument 1 from "const char * " to "std::_String_iterator<std::_String_val>
我正在尝试使用boost.spirit库为csv文件编写一个解析器。我遇到以下编译错误。我是boost.spirit的新手,有人能找出原因吗?
错误消息为:
错误C2664:"bool boost::spirit::qi::rule::parse(Iterator&,const Iterator&,Context&、const Skipper&、Attribute&)const":无法将参数1从"const char*"转换为"std::_String_Iterator>>&"
我的代码是:
#pragma once
#define BOOST_SPIRIT_USE_PHOENIX_V3
#include<vector>
#include<string>
#include<memory>
#include<boost/iostreams/device/mapped_file.hpp> // for mmap
#include<boost/utility/string_ref.hpp>
#include<boost/spirit/include/qi.hpp>
#include<boost/spirit/include/qi_grammar.hpp>
#include<boost/spirit/include/qi_real.hpp>
#include<boost/spirit/include/phoenix.hpp>
#include<boost/spirit/include/qi_symbols.hpp>
typedef boost::string_ref CsvField;
typedef std::vector<CsvField> CsvLine;
typedef std::vector<CsvLine> CsvFile;
namespace qi = boost::spirit::qi;
template <typename T> struct CsvParser : qi::grammar<T, CsvFile()> {
CsvParser() : CsvParser::base_type(lines) {
using namespace qi;
using boost::phoenix::construct;
using boost::phoenix::size;
using boost::phoenix::begin;
using boost::spirit::qi::float_;
field = raw[*~char_(",rn")][_val = construct<CsvField>(begin(qi::_1), size(qi::_1))]; // semantic action
//field = qi::float_;
line = field % ',';
lines = line % eol;
}
// declare: line, field, fields
qi::rule<T, CsvFile()> lines;
qi::rule<T, CsvLine()> line;
qi::rule<T, CsvField()> field;
};
该代码实际上是从读取映射到内存的CSV文件的最简单方法中采用的,所以我没有任何线索。我正在使用Microsoft Visual Studio 2015和boost 1.16.0.
如果我用typedef std::string
替换typedef boost::string_ref CsvField
,或者用field = *(~char_(",rn"))
替换字段的解析器,也会出现同样的错误。
此外,我正在解析的文件实际上是一个标准的csv文件,因此欢迎任何其他解析方法的建议。唯一的问题是这个文件有数百万行,所以标准的逐行解析对我来说不起作用
您没有显示相关的代码。您所拥有的只是一个模板类,但任何实例化是否形成良好取决于您用什么实例化它。
现在,我假设您正在尝试使用std::string::const_iterator
作为迭代器类型进行实例化——这有点有趣,因为提到了内存映射和字符串ref(这意味着您希望做任何事情都是零拷贝)。
然而,问题是raw[]
公开了源迭代器类型的迭代器范围,这意味着您将std::string::const_iterator
作为string_ref
(别名CsvField
)构造函数的第一个参数传递。那行不通。
在修复中:
field = raw[*~char_(",rn")][_val = construct<CsvField>(&*begin(qi::_1), size(qi::_1))]; // semantic action
要想真的好看,你应该把std::addressof
包装成一个phoenix演员,并用它代替operator&
。我将把它留给读者练习。
在Coliru上直播
#define BOOST_SPIRIT_USE_PHOENIX_V3
#include<boost/utility/string_ref.hpp>
#include<boost/spirit/include/qi.hpp>
#include<boost/spirit/include/phoenix.hpp>
typedef boost::string_ref CsvField;
typedef std::vector<CsvField> CsvLine;
typedef std::vector<CsvLine> CsvFile;
namespace qi = boost::spirit::qi;
template <typename T> struct CsvParser : qi::grammar<T, CsvFile()> {
CsvParser() : CsvParser::base_type(lines) {
using namespace qi;
using boost::phoenix::construct;
using boost::phoenix::size;
using boost::phoenix::begin;
using boost::spirit::qi::float_;
field = raw[*~char_(",rn")][_val = construct<CsvField>(&*begin(qi::_1), size(qi::_1))]; // semantic action
//field = qi::float_;
line = field % ',';
lines = line % eol;
}
// declare: line, field, fields
qi::rule<T, CsvFile()> lines;
qi::rule<T, CsvLine()> line;
qi::rule<T, CsvField()> field;
};
int main()
{
using It = std::string::const_iterator;
CsvParser<It> p;
std::string const input = R"([section1]
key1=value1
key2=value2
[section2]
key3=value3
key4=value4
)";
CsvFile parsed;
auto f = input.begin(), l = input.end();
bool ok = parse(f, l, p, parsed);
if (ok) {
std::cout << "Parsed: " << parsed.size() << " stuffsn";
} else {
std::cout << "Parse failedn";
}
if (f != l)
std::cout << "Remaining input: '" << std::string(f, l) << "'n";
}
打印:
Parsed: 7 stuffs
- cppcheck在const std::string[]上引发警告
- 将std::string传递给WriteConsole API
- 为std::string的某个索引赋值
- 使用 std::string () const 函数启动线程或未来
- 当我们进行一些操作时,应该使用什么'std::string'或'std::stringstream'?
- 如何更改大小(std::string)
- std::string 的对象真的可以移动吗?
- SegFault 同时使用 std::string::operator+= 和函数作为参数
- 无法从 std::string 中提取C++ Unicode 符号
- std::string 构造函数如何处理固定大小的 char[]?
- 真的没有来自 std::string_view 的 std::string 的显式构造函数吗?
- 将C++ std::string 转换为 UTF-16-LE 编码的字符串
- 重载 + 自己的类和 std::string 的运算符
- 如何使用 std::string 作为 QHash 的键?
- 将日语 wstring 转换为 std::string
- 可以从std::string继承以提供类型一致性吗
- 构造函数采用std::string_view与std::string并移动
- 在共享缓冲区内存中创建 ::std::string 对象
- std::string.size() 未知行为
- Valgrind 在 std::string::swap 中报告 SIGILL