boost::spirit::qi compiler error: cannot convert 'const some_stuff::return_type' to 'unsigned int' without a conversion operator

boost::spirit::qi compiler error: cannot convert 'const some_stuff::return_type' to 'unsigned int' without a conversion operator

我在使用 boost1.54 和 clang++-3.9 编写的程序中遇到编译错误。 考虑以下(简化的)示例代码:

#include <boost/fusion/include/adapt_struct.hpp>
#include <boost/spirit/include/qi.hpp>
#include <iostream>
#include <string>

using namespace boost::spirit;

struct some_stuff {
    struct return_type {
        unsigned int field_1;
    };

    struct id : qi::grammar<std::string::iterator>{
        id() : id::base_type(rule_){ rule_ = qi::lit("?AL"); }
    private:
        qi::rule<std::string::iterator> rule_;
    };

    struct payload : qi::grammar<std::string::iterator, return_type()> {
        payload() : payload::base_type{rule_} { rule_ = qi::uint_; }
    private:
        qi::rule<std::string::iterator, return_type()> rule_;
    };
};
BOOST_FUSION_ADAPT_STRUCT(some_stuff::return_type, (unsigned int, field_1))

struct my_grammar : qi::grammar<std::string::iterator, some_stuff::return_type()>{
    my_grammar() : my_grammar::base_type(rule_){ rule_ = "+++AT" >> i_ >> ':' >> qi::omit[qi::uint_] >> ':' >> p_; }
private:
    some_stuff::id i_;
    some_stuff::payload p_;
    qi::rule<std::string::iterator, some_stuff::return_type()> rule_;
};

int main() {
    std::string s("+++AT?AL:1:3,5");
    my_grammar g_;
    some_stuff::return_type v_;

    auto it = s.begin();
    if (qi::phrase_parse(it, s.end(), g_, ascii::space, v_)) {
        std::cout << "Field 1: " << v_.field_1 << std::endl;
    }
    return 0;
}

当我尝试编译它时,我得到了标题中报告的错误:

error: cannot convert 'const some_stuff::return_type' to 'unsigned int' without a conversion operator 

但是,如果我将转换运算符添加到结构 some_stuff::return_type 中的 unsigned int,则一切正常。 有人可以帮助我理解为什么在这种情况下强制转换运算符是强制性的,或者如果不是强制性的,如何解决这个问题?

你被臭名昭著的 "single-element sequence" bug/limitation 咬了:Spirit Qi attribute propagation issue with single-member struct

dummy 字段添加到 return_type 使其工作(还添加了调试):

Live On Coliru

#define BOOST_SPIRIT_DEBUG
#include <boost/fusion/include/adapt_struct.hpp>
#include <boost/spirit/include/qi.hpp>
#include <iostream>
#include <string>

using namespace boost::spirit;

struct some_stuff {
    struct return_type {
        unsigned int field_1;
        bool dummy;
    };

    struct id : qi::grammar<std::string::iterator> {
        id() : id::base_type(rule_) {
            rule_ = qi::lit("?AL"); 
            BOOST_SPIRIT_DEBUG_NODES((rule_))
        }

      private:
        qi::rule<std::string::iterator> rule_;
    };

    struct payload : qi::grammar<std::string::iterator, return_type()> {
        payload() : payload::base_type{ rule_ } {
            rule_ = qi::uint_ >> qi::attr(false); 
            BOOST_SPIRIT_DEBUG_NODES((rule_))
        }

      private:
        qi::rule<std::string::iterator, return_type()> rule_;
    };
};
BOOST_FUSION_ADAPT_STRUCT(some_stuff::return_type, field_1, dummy)

struct my_grammar : qi::grammar<std::string::iterator, some_stuff::return_type()> {
    my_grammar() : my_grammar::base_type(rule_) {
        rule_ = "+++AT" >> i_ >> ':' >> qi::omit[qi::uint_] >> ':' >> p_; 
        BOOST_SPIRIT_DEBUG_NODES((rule_))
    }

  private:
    some_stuff::id i_;
    some_stuff::payload p_;
    qi::rule<std::string::iterator, some_stuff::return_type()> rule_;
};

int main() {
    std::string s("+++AT?AL:1:3,5");
    my_grammar g_;
    some_stuff::return_type v_;

    auto it = s.begin();
    if (qi::phrase_parse(it, s.end(), g_, ascii::space, v_)) {
        std::cout << "Field 1: " << v_.field_1 << std::endl;
    }
}

版画

<rule_>
  <try>+++AT?AL:1:3,5</try>
  <rule_>
    <try>?AL:1:3,5</try>
    <success>:1:3,5</success>
    <attributes>[]</attributes>
  </rule_>
  <rule_>
    <try>3,5</try>
    <success>,5</success>
    <attributes>[[3, 0]]</attributes>
  </rule_>
  <success>,5</success>
  <attributes>[[3, 0]]</attributes>
</rule_>
Field 1: 3

注意

您使用的 phrase_parse 没有船长。那行不通,也不是您想要的:Boost spirit skipper issues