C++ boost::spirit:: карма для вариантов

У меня есть импульс:: вариант в моей программе, которая принимает типы double, uint16_t, std::stringи т.д. Я храню их, и я хотел бы использовать boost::karma генерировать / распечатывать их. Я новичок в boost::spirit но я понимаю, что это хорошо работает с вариантами. Какие варианты я должен пойти по этому поводу? Как будет выглядеть простая грамматика / правило для генерации одного из них? Любая помощь будет отличной!

1 ответ

Решение

1. Правила простоты

Абсолютно простой пример, который я могу придумать, демонстрирует, как карма может синтезировать auto_ Правило для вашего конкретного варианта на лету [1]:

#include <boost/spirit/include/karma.hpp>    
namespace karma = boost::spirit::karma;

int main() {
    typedef boost::variant<double, unsigned int, std::string> V;

    for(auto v : { V{42u}, V{3.1416}, V{"Life Of Pi"} })
        std::cout << karma::format(karma::auto_, v) << "\n";
}

Печать:

42
3.142
Life Of Pi

Проще простого!

Эквивалент в отдельной грамматике: Live On Coliru

2. Более сложный образец

Более сложная грамматика (также Live On Coliru), которая показывает, как волшебная совместимость атрибутов Spirit управляет DoTheRightThing™:

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

namespace karma = boost::spirit::karma;

typedef boost::variant<double, unsigned int, std::string> V;

struct gen : karma::grammar<boost::spirit::ostream_iterator, V()> {
    gen() : gen::base_type(start) 
    {
        using namespace karma;

        start = my_real | my_uint | my_text;

        my_uint = "The value is unsigned integral value (" << uint_ << ")";
        my_real = "The value is double precision floating point value (" << double_ << ")";
        my_text = "The value is an epos: '" << *quoted_char << "'";

        quoted_char = '\\' << char_("'") | graph | "\\x" << uint_generator<uint8_t, 16>();
    }
  private:
    karma::rule<boost::spirit::ostream_iterator, V()>           start;
    karma::rule<boost::spirit::ostream_iterator, double()>      my_real;
    karma::rule<boost::spirit::ostream_iterator, unsigned       int()>   my_uint;
    karma::rule<boost::spirit::ostream_iterator, std::string()> my_text;
    karma::rule<boost::spirit::ostream_iterator, uint8_t()>     quoted_char;
};

int main()
{
    for(auto v : { V{42u}, V{3.1416}, V{"It's a beautiful day!"} })
        std::cout << karma::format(gen(), v) << "\n";
}

Это печатает:

The value is unsigned integral value (42)
The value is double precision floating point value (3.142)
The value is an epos: 'It\'s\x20a\x20beautiful\x20day!'

main также может быть написано как

int main() {
    std::cout << karma::format(gen() % "\n", std::vector<V>{42u,3.1416,"It's a beautiful day!"}) << "\n";
}

Что должно дать вам представление о том, насколько универсальной может быть структура анализатора / генератора духов.


[1] Пока присутствует признак генератора автоматического анализатора; Дух предоставляет их для множества типов, в том числе uint, std::string, double а также variant (но также дополнительные элементы, векторы, карты, все, что можно адаптировать как последовательность Fusion и т. д. и т. д.)

Другие вопросы по тегам