Search code examples
c++boostboost-spiritboost-spirit-karma

Boost::spirit::karma: duplicate doesn't work within repeat or kleene star?


Here's a piece of very simple code that uses boost::spirit::karma to produce formatted output in the graphviz dot language:

#include <iostream>
#include <iterator>
#include <vector>
#include <boost/spirit/include/karma.hpp>
using namespace std;

int main() {
    vector<int> v{0,1,2,3};
    unsigned count = 17;
    {
        namespace karma = boost::spirit::karma;
        karma::generate(ostream_iterator<char>(cout), *(karma::duplicate['c' << karma::int_ << '_' << karma::lit(count) << "[xlabel=" << karma::int_ << "];\n"]), v);
    }

    return 0;
}

I would expect this to produce:

c0_17[xlabel=0];
c1_17[xlabel=1];
c2_17[xlabel=2];
c3_17[xlabel=3];

Instead, it produced:

c0_17[xlabel=1];
c2_17[xlabel=3];

Which means the duplicate[] directive is not effective at all within a kleene star. I've also tried the repeat[] directive but that does not work as well.

What am I doing wrong? I'm using boost version 1.53.0. I've compiled the code with g++ 4.7 and clang++ 3.2, both produced the same results.


Solution

  • #include <iostream>
    #include <iterator>
    #include <vector>
    #include <boost/spirit/include/karma.hpp>
    using namespace std;
    
    int main() {
        vector<int> v{0,1,2,3};
        unsigned count = 17;
        {
            namespace karma = boost::spirit::karma;
            //karma::rule<ostream_iterator<char>, int()> xlabel = karma::duplicate['c' << karma::int_ << '_' << karma::lit(count) << "[xlabel=" << karma::int_ << "];\n"];
            //karma::generate(ostream_iterator<char>(cout), *xlabel, v);
            karma::generate(ostream_iterator<char>(cout), *karma::attr_cast<int>(karma::duplicate['c' << karma::int_ << '_' << karma::lit(count) << "[xlabel=" << karma::int_ << "];\n"]), v);
        }
    
        return 0;
    }