質問

boost::variant<boost::container::vector<int>, std::string> tmp = "test";
std::string use;
namespace karma = boost::spirit::karma;
bool r = karma::generate(std::back_insert_iterator<std::string>(use), +karma::int_ |   *karma::char_, tmp);

The result is r = false, use = "". However, I expect use = "test".

There is another example

boost::variant<std::vector<int>, std::string> tmp = "test";
std::string use;
namespace karma = boost::spirit::karma;
bool r = karma::generate(std::back_insert_iterator<std::string>(use), +karma::int_ |  +karma::char_, tmp);

The result is still r = false, use = "". However. What' wrong?

役に立ちましたか?

解決

There is a big difference between how the alternative parser and alternative generator work. The alternative parser tries to match its operands one by one until one of them succeeds. In contrast the alternative generator uses the operand that matches exactly the attribute you want to generate and if there is none that matches it does nothing. If there are several that do match, those are tried one by one until one of them succeeds. The easiest way to solve your problem is creating karma::rules that expose the exact attributes in your variant.

Example on Coliru

#include <iostream>
#include <vector>
#include <boost/spirit/include/karma.hpp>
#include <boost/container/vector.hpp>

int main()
{
    boost::variant<boost::container::vector<int>, std::string> tmp = "test";
    std::string use;
    namespace karma = boost::spirit::karma;
    //Your original code
    bool r = karma::generate(std::back_insert_iterator<std::string>(use), +karma::int_ |   *karma::char_, tmp);
    std::cout << "r=" << std::boolalpha << r << ", Use: \""<< use << '"' << std::endl;

    //Create rules to expose explicitly the attributes you want
    use.clear();
    karma::rule<std::back_insert_iterator<std::string>,boost::container::vector<int>()> ints_rule = karma::int_%',';
    karma::rule<std::back_insert_iterator<std::string>,std::string()> string_rule = *karma::char_;
    r = karma::generate(std::back_insert_iterator<std::string>(use), ints_rule | string_rule, tmp);
    std::cout << "r=" << std::boolalpha << r << ", Use: \""<< use << '"' << std::endl;

    //Same test using ints
    use.clear();
    boost::container::vector<int> tmp_vector;
    tmp_vector.push_back(1);
    tmp_vector.push_back(2);
    tmp=tmp_vector;
    r = karma::generate(std::back_insert_iterator<std::string>(use), ints_rule | string_rule, tmp);
    std::cout << "r=" << std::boolalpha << r << ", Use: \""<< use << '"' << std::endl;

    //An example in which the variant has the exact same attributes exposed by the alternative generator
    use.clear();
    boost::variant<std::vector<int>, std::vector<char> > tmp2;
    std::vector<char> string;
    string.push_back('t');
    string.push_back('e');
    string.push_back('s');
    string.push_back('t');
    tmp2=string;
    r = karma::generate(std::back_insert_iterator<std::string>(use), karma::int_%',' | *karma::char_,tmp2);
    std::cout << "r=" << std::boolalpha << r << ", Use: \""<< use << '"' << std::endl;
}
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top