1

ドキュメントには、AとBの両方を使用する場合、2つの複合ルール(a >> b)の属性はタプルである必要があると記載されています。

これを想定して、そのようなタプルの最初の属性を読み取ろうとしました。しかし、失敗します:(
解析された整数を'i'に格納しようとします)

#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix_core.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>
#include <boost/spirit/include/phoenix_object.hpp>

template <typename ForwardIterator> class TestGrammar
: public boost::spirit::qi::grammar<ForwardIterator, boost::spirit::ascii::space_type>
{
    boost::spirit::qi::rule<ForwardIterator, boost::spirit::ascii::space_type> foo_;
public:
    TestGrammar( void ) : TestGrammar::base_type( foo_ )
    {
        int i;
        foo_ = ((boost::spirit::qi::int_ >> boost::spirit::qi::float_)
                      [boost::phoenix::ref(i) = boost::phoenix::at_c<0>(boost::spirit::_1)]);
    }
};

int main( void )
{
    TestGrammar<std::string::iterator> g;

    return 0;
}

書き込み:

foo_ = ((boost::spirit::qi::int_ >> boost::spirit::qi::float_)
                     [boost::phoenix::ref(i) = boost::spirit::_1]);

Aがintである限り、常に機能します。
タイプを前後に変更し、カスタムルールを作成すると、(a >> b)の属性はBが何であるかに関係なく常にAになることが明らかになりました。

4

2 に答える 2

2

私はあなたがこれをしたかったと思います:

int i;
float f;
foo_ = (boost::spirit::qi::int_ >> boost::spirit::qi::float_)
             [ boost::phoenix::ref(i) = boost::spirit::_1,
               boost::phoenix::ref(f) = boost::spirit::_2 ];

本当にシーケンスを使用したい場合は、次を試してください。

foo_ = qi::attr_cast<>(qi::int_ >> qi::float_)
                [ boost::phoenix::ref(i) = phx::at_c<0>(qi::_1),
                  boost::phoenix::ref(f) = phx::at_c<1>(qi::_1) ]

またはヘルパールールを使用して:

helper = qi::int_ >> qi::float_;
foo_ = helper
                [ boost::phoenix::ref(i) = phx::at_c<0>(qi::_1),
                  boost::phoenix::ref(f) = phx::at_c<1>(qi::_1) ]
    ;

http://liveworkspace.org/code/518f2bd03e1fed7ed734d62071a88eabでコンパイルされている3つのバージョンすべて

于 2012-09-02T23:13:07.953 に答える
1

これをコンパイルする場合:

struct TestDelegate
{
    template <typename T, typename U, typename V>
    void operator()(T const& t, U const& u, V const& v) const {
        bar;
    }
};

template <typename ForwardIterator> class TestGrammar
: public boost::spirit::qi::grammar<ForwardIterator, boost::spirit::ascii::space_type>
{
    boost::spirit::qi::rule<ForwardIterator, boost::spirit::ascii::space_type> foo_;
public:
    TestGrammar( void ) : TestGrammar::base_type( foo_ )
    {
        //int i;
        TestDelegate test_delegate;
        //foo_ = ((boost::spirit::qi::int_ >> boost::spirit::qi::float_)
        //              [boost::phoenix::ref(i) = boost::phoenix::at_c<0>(boost::spirit::_1)]);
        foo_ = ((boost::spirit::qi::int_ >> boost::spirit::qi::float_)
                      [test_delegate]);
    }
};

int main( void )
{
    TestGrammar<std::string::iterator> g;

    return 0;
}

結果のエラーエッセイで、属性タイプがタプルであることがわかります。

1>e:\work\test\spiritprob\spiritprob\spiritprob.cpp(14) : error C2065: 'bar' : undeclared identifier
1>        e:\boost\boost_1_44_0\boost_1_44_0\boost\spirit\home\support\action_dispatch.hpp(29) : see reference to function template instantiation 'void TestDelegate::operator ()<Attribute,Context,bool>(const T &,const U &,const V &) const' being compiled
1>        with
1>        [
1>            Attribute=boost::fusion::vector2<int,float>,
1>            Context=boost::spirit::context<boost::fusion::cons<boost::fusion::unused_type &,boost::fusion::nil>,boost::fusion::vector0<>>,
1>            T=boost::fusion::vector2<int,float>,
1>            U=boost::spirit::context<boost::fusion::cons<boost::fusion::unused_type &,boost::fusion::nil>,boost::fusion::vector0<>>,
1>            V=bool
1>        ]

(Visual Studio 2008でコンパイル)

私たちの問題を直接解決するわけではありませんが、少なくともあなたはそれがfusion::vector<int,float>

于 2012-09-02T19:27:16.437 に答える