为什么 boost::spirit::qi::p arse() 没有设置这个 boost::variant 的值?

Why does boost::spirit::qi::parse() not set this boost::variant's value?

本文关键字:boost 设置 的值 variant qi spirit arse 为什么      更新时间:2023-10-16

当尝试将文本解析为boost::变体时,变体的值不会被更改。解析器本身似乎工作得很好,所以我的假设是我在变体代码中做错了什么。

我使用boost 1.46.1和,下面的代码在 Visual Studio 2008中编译。

1日更新

hkaiser注意到规则和语法模板参数不能是Variant,而是Variant()
这有一点"进一步"。因为我现在有一个编译错误在boost_1_46_1boostvariantvariant.hpp(1304)。注释说:

// NOTE TO USER :
// Compile error here indicates that the given type is not 
// unambiguously convertible to one of the variant's types
// (or that no conversion exists).

显然,表达式(qi::double_ | +qi::char_)的属性不是boost::variant<double, std::string>。但那是什么呢?

2日更新

使用typedef boost::variant<double, std::vector<char>> Variant;对解析器有效。但是,这并不像std::string…

那样容易使用。
#include <boost/spirit/include/qi.hpp>
#include <boost/variant.hpp>
int main()
{
    namespace qi = boost::spirit::qi;
    typedef std::string::const_iterator Iterator;
    const std::string a("foo"), b("0.5");
    // This works
    {
        std::string stringResult;
        Iterator itA = a.begin();
        const bool isStringParsed =
            qi::parse(itA, a.end(), +qi::char_, stringResult);
        double doubleResult = -1;
        Iterator itB = b.begin();
        const bool isDoubleParsed =
            qi::parse(itB, b.end(), qi::double_, doubleResult);
        std::cout
                << "A Parsed? " << isStringParsed <<
                ", Value? " << stringResult << "n"
                << "B Parsed? " << isDoubleParsed <<
                ", Value? " << doubleResult << std::endl;
        // Output:
        // A Parsed? 1, Value? foo
        // B Parsed? 1, Value? 0.5
    }

    // This also works now
    {
        typedef boost::variant<double, std::vector<char>> Variant; // vector<char>, not string!
        struct variant_grammar : qi::grammar<Iterator, Variant()> // "Variant()", not "Variant"!
        {
            qi::rule<Iterator, Variant()> m_rule; // "Variant()", not "Variant"!
            variant_grammar() : variant_grammar::base_type(m_rule)
            {
                m_rule %= (qi::double_ | +qi::char_);
            }
        };
        variant_grammar varGrammar;
        Variant varA(-1), varB(-1);
        Iterator itA = a.begin();
        const bool isVarAParsed = qi::parse(itA, a.end(), varGrammar, varA);
        Iterator itB = b.begin();
        const bool isVarBParsed = qi::parse(itB, b.end(), varGrammar, varB);
        // std::vector<char> cannot be put into std::cout but
        // needs to be converted to a std::string (or char*) first.
        // The conversion I came up with is very ugly but it's not the point
        // of this question anyway, so I omitted it.
        // You'll have to believe me here, when I'm saying it works..
        // Output:
        // A (variant): Parsed? 1, Value? foo, Remaining text = ''
        // B (variant): Parsed? 1, Value? 0.5, Remaining text = ''
    }
    return 0;
}

规则的属性必须使用函数声明语法指定:

qi::rule<Iterator, Variant()> m_rule;

我没有尝试过,但我相信它会在这个改变后工作(同样是需要语法,顺便说一句)。