【问题标题】:Boost Spirit Visual C++ compiler error, fine with GCCBoost Spirit Visual C++ 编译器错误,GCC 很好
【发布时间】:2015-12-08 20:13:55
【问题描述】:

我无法在 Visual C++ (2015) 下编译以下 live demo code。该代码在 GCC 中作为 demonstrated here 运行良好。有人可以帮我解决这个问题。我对提升灵气解析还很陌生,并且在后台使用所有模板魔法,很难发现问题。我从堆栈溢出中的 here 获得了 CSV 解析的初步灵感。

visual C++(通过在线实时编译器)报出的编译器错误如下:

Error(s):
source_file.cpp(103): error C2146: syntax error: missing ';' before identifier 'context_type'
source_file.cpp(140): note: see reference to class template instantiation 'CsvGrammar<It>::final' being compiled
source_file.cpp(147): note: see reference to class template instantiation 'CsvGrammar<It>' being compiled
source_file.cpp(103): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
source_file.cpp(146): error C2079: 'CsvGrammar<std::_String_const_iterator<std::_String_val<std::_Simple_types<char>>>>::convert' uses undefined struct 'CsvGrammar<std::_String_const_iterator<std::_String_val<std::_Simple_types<char>>>>::final'
source_file.cpp(158): note: see reference to class template instantiation 'CsvGrammar<std::_String_const_iterator<std::_String_val<std::_Simple_types<char>>>>' being compiled

我桌面的visual C++2015下的错误如下图:

1>------ Build started: Project: ConsoleApplication1, Configuration: Debug x64 ------
1>  Source.cpp
1>\\geihome1\home\jcoffey\visual studio 2015\projects\consoleapplication1\consoleapplication1\source.cpp(103): error C2146: syntax error: missing ';' before identifier 'context_type'
1>  \\geihome1\home\jcoffey\visual studio 2015\projects\consoleapplication1\consoleapplication1\source.cpp(140): note: see reference to class template instantiation 'CsvGrammar<It>::final' being compiled
1>  \\geihome1\home\jcoffey\visual studio 2015\projects\consoleapplication1\consoleapplication1\source.cpp(147): note: see reference to class template instantiation 'CsvGrammar<It>' being compiled
1>\\geihome1\home\jcoffey\visual studio 2015\projects\consoleapplication1\consoleapplication1\source.cpp(103): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1>\\geihome1\home\jcoffey\visual studio 2015\projects\consoleapplication1\consoleapplication1\source.cpp(146): error C2079: 'CsvGrammar<std::_String_const_iterator<std::_String_val<std::_Simple_types<char>>>>::convert' uses undefined struct 'CsvGrammar<std::_String_const_iterator<std::_String_val<std::_Simple_types<char>>>>::final'
1>  \\geihome1\home\jcoffey\visual studio 2015\projects\consoleapplication1\consoleapplication1\source.cpp(158): note: see reference to class template instantiation 'CsvGrammar<std::_String_const_iterator<std::_String_val<std::_Simple_types<char>>>>' being compiled
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

这是有问题的代码(也复制到上面指出的现场演示站点)

#define BOOST_SPIRIT_USE_PHOENIX_V3
#include <iostream>
#include <boost/fusion/include/at_c.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>
#include <string>
#include <vector>

namespace qi = boost::spirit::qi;
namespace phx = boost::phoenix;

enum LineItems {
    SERVICENAME,
    POLYNOMIAL,
    MODULE,
    DLMUW,
    WSU,
    TCP,
    UDP,
    INAIR,
    CLIENTS,
//    RXPORTDCTRL,
//    TXPORTDCTRL,
//    RXPORTWCTRL,
//    TXPORTWCTRL,
//    RXPORTD1,
//    TXPORTD1,
//    RXPORTD2,
//    TXPORTD2,
//    RXPORTD3,
//    TXPORTD3,
//    RXPORTD4,
//    TXPORTD4,
//    RXPORTW1,
//    TXPORTW1,
//    RXPORTW2,
//    TXPORTW2
};

struct CsvLine {
    std::string ServiceName;
    std::string Polynomial;
    std::string Module;
    int DLMUW;
    int WSU;
    int TCP;
    int UDP;
    int InAir;
    int Clients;
//    std::string RxPortDCtrl;
//    std::string TxPortDCtrl;
//    std::string RxPortWCtrl;
//    std::string TxPortWCtrl;
//    int RxPortD1;
//    int TxPortD1;
//    int RxPortD2;
//    int TxPortD2;
//    int RxPortD3;
//    int TxPortD3;
//    int RxPortD4;
//    int TxPortD4;
//    int RxPortW1;
//    int TxPortW1;
//    int RxPortW2;
//    int TxPortW2;
};

using Column  = std::string;
using Columns = std::vector<Column>;
using CsvFile = std::vector<CsvLine>;

template<typename It>
struct CsvGrammar: qi::grammar<It, CsvFile(), qi::locals<std::vector<LineItems>>, qi::blank_type> {
    CsvGrammar() : CsvGrammar::base_type(start) {
        using namespace qi;
        static const char colsep = ',';

        item.add("ServiceName", SERVICENAME)("Polynomial", POLYNOMIAL)("Module", MODULE)("DLMUW", DLMUW)("WSU", WSU)("TCP", TCP)("UDP", UDP)("InAir", INAIR)("Clients", CLIENTS);
        start  = qi::omit[ header[_a=_1] ] >> eol >> line(_a) % eol;

        // Module was unused
        header = (item | omit[column] >> attr(MODULE)) % colsep;
        line   = (column % colsep) [convert];

        column = quoted | *~char_(",\n");
        quoted = '"' >> *("\"\"" | ~char_("\"\n")) >> '"';

        BOOST_SPIRIT_DEBUG_NODES((header)(column)(quoted));
    }

private:
    qi::rule<It, std::vector<LineItems>(),                      qi::blank_type> header;
    qi::rule<It, CsvFile(), qi::locals<std::vector<LineItems>>, qi::blank_type> start;
    qi::rule<It, CsvLine(std::vector<LineItems> const&),        qi::blank_type> line;

    qi::rule<It, Column(), qi::blank_type> column;
    qi::rule<It, std::string()> quoted;
    qi::rule<It, qi::blank_type> empty;

    qi::symbols<char, LineItems> item;

    struct final {
        using Ctx = typename decltype(line)::context_type;

        void operator()(Columns const& columns, Ctx &ctx, bool &pass) const {
            auto& csvLine   = boost::fusion::at_c<0>(ctx.attributes);
            auto& positions = boost::fusion::at_c<1>(ctx.attributes);
            int i =0;

            for (LineItems position : positions) {
                switch (position) {
                case SERVICENAME: 
                    csvLine.ServiceName = columns[i];              
                    break;
                case POLYNOMIAL:  
                    csvLine.Polynomial = columns[i]; 
                    break;
                case MODULE:  
                    csvLine.Module = columns[i]; 
                    break;
                case DLMUW:
                    csvLine.DLMUW = atoi(columns[i].c_str()); 
                    break;
                case WSU:
                    csvLine.WSU = atoi(columns[i].c_str()); 
                    break;
                case TCP:
                    csvLine.TCP = atoi(columns[i].c_str()); 
                    break;
                case UDP:
                    csvLine.UDP = atoi(columns[i].c_str()); 
                    break;
                case INAIR:
                    csvLine.InAir = atoi(columns[i].c_str()); 
                    break;
                case CLIENTS:
                    csvLine.Clients = atoi(columns[i].c_str()); 
                    break;
                default:   
                    break;
                }
                i++;
            }
            pass = true; // returning false fails the `line` rule
        }
    } convert;
};

int main() {
    const std::string s =
        "ServiceName,Polynomial,Module,DLMUW,WSU,TCP,UDP,InAir,Clients\n"
        "ALBF,0x82608EDB,nic1,1,0,1,1,1,6\n"
        "OmsMIS,0x04C11DB7,cmc,1,0,1,1,1,5\n"
        "FMS1,0x82F63B78,proc3,1,0,1,1,1,4\n"
        "FMS2,0x82F63B78,proc5,1,0,1,1,1,3";

    auto f(begin(s)), l(end(s));
    CsvGrammar<std::string::const_iterator> p;

    CsvFile parsed;
    bool ok = qi::phrase_parse(f, l, p, qi::blank, parsed);

    if (ok) {
        for (CsvLine line : parsed) {
            std::cout 
                << '[' << line.ServiceName << ']' 
                << '[' << line.Polynomial << ']' 
                << '[' << line.Module << ']' 
                << '[' << line.DLMUW << ']' 
                << '[' << line.WSU << ']'
                << '[' << line.TCP << ']'
                << '[' << line.UDP << ']'
                << '[' << line.InAir << ']'
                << '[' << line.Clients << ']';
            std::cout << std::endl;
        }
    } else {
        std::cout << "Parse failed\n";
    }

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

【问题讨论】:

  • 您是否已经检查了CLIENTS, 中的逗号?
  • @Marged 是的,除此之外这是完全有效的,这不是问题
  • 它所说的只是LineItems 未声明。您确定您正在编译的代码与上面显示的完全相同相同吗?
  • @JesseGood 是的,如果您愿意,您可以尝试使用实时链接,我认为 LineItems 以某种方式混淆了“struct CsvGrammar: qi::grammar>, qi::blank_type> { " line
  • @JesseGood 抱歉,我从 Visual Studio 发布了一些不正确的错误 - 刚刚更新,您说得很好,因为我之前发布的错误来自我以前的构建,我的错

标签: c++ csv boost boost-spirit boost-spirit-qi


【解决方案1】:

我很确定这是 MSVC 中的一个错误。由于某种原因,编译器在decltype 上阻塞(因为这是一个语法错误,很可能他们还没有实现它)。这是一个解决方法:

using workaround = decltype(line);
using Ctx = typename workaround::context_type;

This seems like the related bug report。它已关闭为deferred... :(

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-13
    • 2012-10-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多