2013-12-10 2 views
1
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); 

Результат: r = false, use = "". Однако я ожидаю, что use = "test".Использование контейнера для хранения контейнера в карме

Существует еще один пример

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); 

В результате по-прежнему г = ложно, используйте = "". Однако. Что случилось?

ответ

0

Существует большая разница между тем, как работает альтернативный парсер и альтернативный генератор. Альтернативный парсер пытается сопоставить свои операнды один за другим, пока один из них не удастся. Напротив, альтернативный генератор использует операнд, который соответствует точно атрибуту, который вы хотите сгенерировать, и если его нет, он ничего не делает. Если есть несколько, которые соответствуют друг другу, они проверяются один за другим, пока один из них не удастся. Самый простой способ решить вашу проблему - создать karma::rule s, которые отображают точные атрибуты в вашем варианте.

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; 
} 
+0

Спасибо. Ты прав. Карма не могла обрабатывать std :: string как вектор автоматически. – vipcxj

Смежные вопросы