Boost logo

Boost Users :

Subject: Re: [Boost-users] [karma] Losing attribute?
From: Hartmut Kaiser (hartmut.kaiser_at_[hidden])
Date: 2010-02-25 08:37:38


Sebastian,

> >> I've got a Karma generator that should emit a vector of records,
> >> writing
> >> out the index of every entry at the start. My code looks like this
> >> (note
> >> that GEOPOINT is a fusion-adapted struct of two doubles):
> >>
> >
> > Could you please provide a minimal, but still self-contained example
> I
> > could
> > run? That would help me to give you a proper answer to your question.
> From
> > what I can see your code should work just fine.
>
> This is the test program I'm using, minus a special float formatter.

Thanks! Please see comments inline below.

> #include <boost/fusion/include/adapt_struct.hpp>
> #include <boost/fusion/include/vector.hpp>
> #include <boost/spirit/include/karma.hpp>
> #include <boost/spirit/include/phoenix.hpp>
> #include <iostream>
> #include <vector>
>
> namespace ph = boost::phoenix;
> namespace km = boost::spirit::karma;
>
> struct GEOPOINT
> {
> double x, y;
> };
> BOOST_FUSION_ADAPT_STRUCT(
> GEOPOINT,
> (double, x)
> (double, y)
> )
>
> typedef std::vector<GEOPOINT> Contour;
> typedef std::vector<Contour> Poly;
>
> template <typename Iterator>
> class ZoneWriter : public km::grammar<Iterator, Poly()>
> {
> public:
> ZoneWriter() : base_type(start)
> {
> using namespace km;
> point = L';' << double_ << L';' << double_;
>
> contour = L";SUBPOLYGON " << lit(_r1 - 1) << L" POINTS " <<
> lit(ph::size(_val)) << L" MASK XOR" << *point;
>
> polygon = L"POLYGON COUNT " << lit(ph::size(_val)) <<
> *(contour(_a)[++_a]);

The reason for the behavior you're seeing is in the line above. The
operator=() for rules applies auto attribute propagation to the expression
only as long as no semantic actions are attached to any of the
sub-expressions of the right hand side. In order to force auto attribute
propagation in your case you need to write that as:

                polygon %= L"POLYGON COUNT " << lit(ph::size(_val)) <<
                        *(contour(_a)[++_a]);

After this change the output looks like what you might have expected...

> start = polygon;
> }
>
> private:
> km::rule<Iterator, GEOPOINT()> point;
> km::rule<Iterator, Contour(int)> contour;
> km::rule<Iterator, km::locals<int>, Poly()> polygon;
> km::rule<Iterator, Poly()> start;
> };
>
> int main()
> {
> Poly poly(5);
> for(int i = 0; i < 5; ++i) {
> Contour &c = poly[i];
> c.resize(10);
> for(int j = 0; j < 10; ++j) {
> c[j].x = i + j / 4.25129;
> c[j].y = -j + i / 1.24951;
> }
> }
> typedef std::ostreambuf_iterator<wchar_t> osbi;
> km::generate(osbi(std::wcout), ZoneWriter<osbi>(), poly);
> std::wcout << L'\n';
> }

BTW, nice example!

HTH
Regards Hartmut

---------------
Meet me at BoostCon
www.boostcon.com


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net