#include<iostream>
#include<string>
#include<vector>

#include<boost/spirit/include/phoenix.hpp> 
#include<boost/spirit/include/karma.hpp>

struct test_spirit
{
  void read_function(std::string &result, std::string const &val) const
  {
    if(result != "memo_zero") result += val;
  }
};

void spirit_01b()
{
  std::vector<std::string> data;
  data.push_back("memo_zero"); data.push_back("memo_two"); 
  data.push_back("memo_three");

  std::string temp;	
  test_spirit ts;
  karma::generate
  (
    std::back_inserter(temp), 
    ( 
      karma::string[phoenix::bind(&test_spirit::read_function, &ts, karma::_1, 
      karma::_val)] << ", "
    ),
    data, data
  );
  std::cout<<temp<<std::endl;

  std::cin.get();
}

The desired output is
"memo_two, memo_three, "(I don't know how to get rid of the last ", ")
The type pass into the function is "std::vector<std::string>"
but what I need is std::string
How could I pass in std::string?

After some experiment, I think semantic action can't do what I want
since result is a temporarily value but now the result I want
(the one wrapped by std::back_inserter)

My original idea is

karma::generate
(
  std::back_inserter(temp), 
  ( !karma::string("memo_two") << karma::string << ", "),
  //+(!karma::string("memo_two") << karma::string << ", ") this line can't work
  data, data
);

How should I solve it?Need to create a new structure and make it adapt to
boost::fusion again?

There are an extremely clumsy solution could solve this

struct attr_struct_2
{
	std::string content;
	std::string content_reference;	
};

BOOST_FUSION_ADAPT_STRUCT
(
  attr_struct_2,
  (std::string, content)
  (std::string, content_reference)	
)

void spirit_02b()
{ 
  std::vector<attr_struct_2> attr;
  attr_struct_2 data; 
  data.content = ("memo_zero"); data.content_reference = data.content; 
  attr.push_back(data);
  data.content = ("memo_one"); data.content_reference = data.content;
  attr.push_back(data);
  data.content = ("memo_two"); data.content_reference = data.content; 
  attr.push_back(data);

  std::string temp;
  typedef std::back_insert_iterator<std::string> sink_type;
  karma::rule<sink_type, std::vector<attr_struct_2>()> rule_00
  = +(!karma::string("memo_two") << karma::string << ", ");
	
  karma::generate(std::back_inserter(temp), rule_00, attr);
  std::cout<<temp<<std::endl;

  std::cin.get();
}

This is too expensive and verbose, do I have other solution?

another solution, but this one need explicit loop

auto end = data.end();
for(auto it = data.begin(); it !=end; ++it)
{
  karma::generate
  (
    std::back_inserter(temp), 
    (!karma::string("memo_two") << karma::string << ", "),
    *it, *it
  );
}
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.