Opened 11 years ago

Closed 11 years ago

#6043 closed Patches (wontfix)

Spirit insists that user types are adapted to Fusion

Reported by: Vladimir Prus Owned by: Joel de Guzman
Milestone: To Be Determined Component: spirit
Version: Boost 1.47.0 Severity: Problem
Keywords: Cc:

Description

I've played with Spirit for the first time, and arrived at the attached example. Basically, I want to create Foo instances from pairs of numbers. This example does not compile unless Foo is adapted to fusion. I don't think this is a good idea, because from the point of view of user, the parser should create instances of Foo, and it's not really clear why parser should iterate over existing instances -- which is what it is trying to do.

Attachments (2)

main.cpp (1.4 KB ) - added by Vladimir Prus 11 years ago.
testcase
main-with-workaround.cpp (1.6 KB ) - added by Vladimir Prus 11 years ago.
testcase with attempted workaround, still does not work for me.

Download all attachments as: .zip

Change History (6)

by Vladimir Prus, 11 years ago

Attachment: main.cpp added

testcase

comment:1 by Vladimir Prus, 11 years ago

On IRC, Thomas produced somewhat easier example. Code the does not work:

#include <boost/spirit/home/qi.hpp>
#include <boost/spirit/home/phoenix.hpp>

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

struct foo
{
    foo(fusion::vector<int, double>) {}
};

int main()
{
    typedef std::string::iterator iterator;

    qi::rule<iterator, foo()> foo_rule;

    foo_rule = (qi::int_ >> qi::double_);
}

Code that does work:

#include <boost/spirit/home/qi.hpp>
#include <boost/spirit/home/phoenix.hpp>

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

struct foo
{
    foo() {}
    foo(int, double) {}
    foo(fusion::vector<int, double>) {}
};

int main()
{
    typedef std::string::iterator iterator;

    qi::rule<iterator, fusion::vector<int, double>()> tuple_rule;
    qi::rule<iterator, foo()> foo_rule;

    tuple_rule = (qi::int_ >> qi::double_);
    foo_rule %= tuple_rule.alias();
}

I frankly don't understand what's going on here, but trying the same workaround for me does not work (with Boost trunk, and gcc 4.5.3), while Thomas reported this new example (main-with-workaround.cpp) compiles for him just fine with 1.47.

by Vladimir Prus, 11 years ago

Attachment: main-with-workaround.cpp added

testcase with attempted workaround, still does not work for me.

comment:2 by anonymous, 11 years ago

Component: Nonespirit
Owner: set to Joel de Guzman

comment:3 by anonymous, 11 years ago

Here's what's happening:

When you have A >> B, the rules are: http://tinyurl.com/bqch2m6

So, as far as compatibility goes, the attribute either has to be a fusion sequence *or* a std container. That is why your code does not compile.

The thing is, spirit is optimal and walks the sequence and builds its elements in-situ, instead of synthesising a temporary sequence in memory and assign later. That is why it has to iterate over existing instances. In this case, it cannot walk a foo. Heller's workaround works because the inner rule is able to walk the fusion sequence and then attribute transformation kicks in whereby it assigns the fusion sequence to foo. That works but is sub optimal.

comment:4 by Joel de Guzman, 11 years ago

Resolution: wontfix
Status: newclosed

Volodya, I'm going to close this as no-fix. If you want to discuss, we can do it in IRC or the mailing lists.

Note: See TracTickets for help on using tickets.