2016-04-14 29 views
1

我正在嘗試使用boost.spirit庫編寫csv文件的解析器。下面的編譯錯誤我在boost.spirit新的,所以可能有人查明原因boost.spirit編譯錯誤:無法將參數1從「const char *」轉換爲「std :: _ St​​ring_iterator <std :: _ St​​ring_val>

的錯誤信息是:?

錯誤C2664:「布爾的boost ::精神::齊::規則::解析(Iterator &,const迭代器&,上下文&,const Skipper &,屬性&)缺點T:爲const char *'不能轉換參數1 '' 到 '的std :: _ St​​ring_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_(",\r\n")][_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; 
}; 

該代碼是真正從Simplest way to read a CSV file mapped to memory?收養,所以我沒有任何線索。我正在使用Microsoft Visual Studio 2015並提升1.16.0。

如果我用typedef std::string替換typedef boost::string_ref CsvField,或者將字段的解析器替換爲field = *(~char_(",\r\n")),則會發生同樣的錯誤。

另外,我解析的文件實際上是一個標準的csv文件,因此任何有關替代解析方法的建議都是值得歡迎的。唯一的問題是該文件有數百萬行,所以標準的逐行解析不適用於我。

回答

0

您未顯示相關代碼。你所擁有的只是一個模板類,但是否有任何實例化是完全取決於你實例化的。

現在我假設你正試圖用std::string::const_iterator作爲迭代器類型實例化 - 這有點搞笑w.r.t.提及內存映射和string_ref(這意味着你希望做一切零拷貝)。

然而,問題是那raw[]暴露源迭代器類型的iterator_range的,這意味着你是路過std::string::const_iterator作爲string_ref(化名CsvField)構造函數的第一個參數。這是行不通的。

進退兩難:

field = raw[*~char_(",\r\n")][_val = construct<CsvField>(&*begin(qi::_1), size(qi::_1))]; // semantic action 

真的不錯,你應該在鳳演員包裹std::addressof,並用它來代替operator&。我將把它作爲讀者的練習。

Live On 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_(",\r\n")][_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() << " stuffs\n"; 
    } else { 
     std::cout << "Parse failed\n"; 
    } 

    if (f != l) 
     std::cout << "Remaining input: '" << std::string(f, l) << "'\n"; 
} 

印刷:

Parsed: 7 stuffs 
相關問題