boost boost-spirit boost-spirit-karma

Comportamiento inconsistente de la columna directiva de Generator en boost karma



boost-spirit boost-spirit-karma (1)

Estoy escribiendo un generador de karma para generar una página HTML y estoy experimentando un comportamiento incoherente mientras uso la directiva de columna. Podría ser mi comprensión de cómo funciona.

Básicamente, estoy generando una grilla que me obliga a insertar algunos delimitadores después de cada 2 apariciones de los datos.

El siguiente es un programa básico que adopté para hacer una prueba.

#include <boost/config/warning_disable.hpp> #include <boost/spirit/include/karma.hpp> #include <boost/fusion/include/struct.hpp> #include <boost/fusion/include/nview.hpp> #include <boost/assign/std/vector.hpp> namespace fusion = boost::fusion; namespace karma = boost::spirit::karma; /////////////////////////////////////////////////////////////////////////////// namespace client { // Our employee struct struct employee { int num; std::string datatype; std::string dataname; std::string inputicon; }; // define iterator type typedef std::back_insert_iterator<std::string> iterator_type; } BOOST_FUSION_ADAPT_STRUCT( client::employee, (int, num) (std::string, datatype) (std::string, dataname) (std::string, inputicon) ) /////////////////////////////////////////////////////////////////////////////// int main() { std::string str; // some employees client::employee john = { 25, "int", "sra_command","fa fa-wrench" }; client::employee mary = { 25, "float", "swt_command","fa fa-wrench" }; client::employee tom = { 25, "double", "msc_command","fa fa-mobile" }; // now make a list of all employees and print them all std::vector<client::employee> employees; { using namespace boost::assign; employees += john, mary, tom; } { typedef fusion::result_of::as_nview<client::employee const, 1, 2, 3>::type names_and_salary; karma::rule<client::iterator_type, names_and_salary()> small_box = "<startofblock>" << karma::string << "<after_first>" << karma::string << "<after_second>" << karma::string << "<after_third>"; std::string generated; typedef std::back_insert_iterator<std::string> sink_type; sink_type sink(generated); karma::generate_delimited(sink, karma::columns(2,karma::string("nth_delimiter"))[small_box % karma::eol],karma::space,employees ); std::cout << generated << std::endl; } return 0; }

Lo anterior genera el siguiente resultado:

<startofblock>int<after_first>sra_command<after_second>fa fa-wrench<after_third> nth_delimiter<startofblock>float<after_first>swt_command<after_second>fa fa-wrench<after_third> nth_delimiter<startofblock>double<after_first>msc_command<after_second>fa fa-mobile<after_third> nth_delimiter

Como se señaló, el delimitador enésimo ocurre después de cada generación en lugar de cada segundo.

El resultado esperado es

<startofblock>int<after_first>sra_command<after_second>fa fa-wrench<after_third> <startofblock>float<after_first>swt_command<after_second>fa fa-wrench<after_third> nth_delimiter<startofblock>double<after_first>msc_command<after_second>fa fa-mobile<after_third>


Creo que esto se acerca a lo que quieres lograr. Como dije, la última ejecución (incompleta) seguirá "terminada" con una etiqueta nth_delimiter :

Live On Coliru

#include <boost/spirit/include/karma.hpp> #include <boost/fusion/include/struct.hpp> #include <boost/fusion/include/nview.hpp> /////////////////////////////////////////////////////////////////////////////// namespace client { struct employee { int num; std::string datatype; std::string dataname; std::string inputicon; }; typedef std::back_insert_iterator<std::string> iterator_type; } BOOST_FUSION_ADAPT_STRUCT(client::employee, /*num,*/ datatype, dataname, inputicon) /////////////////////////////////////////////////////////////////////////////// int main() { // some employees std::vector<client::employee> const employees { { 25, "int", "sra_command","fa fa-wrench" }, { 26, "float", "swt_command","fa fa-wrench" }, { 27, "double", "msc_command","fa fa-mobile" }, { 28, "int", "sra_command","fa fa-wrench" }, { 29, "float", "swt_command","fa fa-wrench" }, { 30, "double", "msc_command","fa fa-mobile" }, { 31, "int", "sra_command","fa fa-wrench" }, { 32, "float", "swt_command","fa fa-wrench" }, { 33, "double", "msc_command","fa fa-mobile" }, }; // now print them all std::string generated; { using namespace boost::spirit::karma; using Sink = client::iterator_type; //using Attr = boost::fusion::result_of::as_nview<client::employee const, 1, 2, 3>::type; using Attr = client::employee; rule<Sink, Attr()> small_box = "<B>" << string << "<1>" << string << "<2>" << string << "<3>"; generate(Sink(generated), columns(2, "<nth_delimiter>/n") [+small_box], employees); } std::cout << generated << std::endl; }

Huellas dactilares

<B>int<1>sra_command<2>fa fa-wrench<3><B>float<1>swt_command<2>fa fa-wrench<3><nth_delimiter> <B>double<1>msc_command<2>fa fa-mobile<3><B>int<1>sra_command<2>fa fa-wrench<3><nth_delimiter> <B>float<1>swt_command<2>fa fa-wrench<3><B>double<1>msc_command<2>fa fa-mobile<3><nth_delimiter> <B>int<1>sra_command<2>fa fa-wrench<3><B>float<1>swt_command<2>fa fa-wrench<3><nth_delimiter> <B>double<1>msc_command<2>fa fa-mobile<3><nth_delimiter>

Prima:

El problema con smallbox % eol es que smallbox es un elemento, y eol también:

generate(Sink(generated), columns(4, "<nth_delimiter>") [small_box % eol], employees);

Live On Coliru

<B>int<1>sra_command<2>fa fa-wrench<3> <B>float<1>swt_command<2>fa fa-wrench<3> <nth_delimiter><B>double<1>msc_command<2>fa fa-mobile<3> <B>int<1>sra_command<2>fa fa-wrench<3> <nth_delimiter><B>float<1>swt_command<2>fa fa-wrench<3> <B>double<1>msc_command<2>fa fa-mobile<3> <nth_delimiter><B>int<1>sra_command<2>fa fa-wrench<3> <B>float<1>swt_command<2>fa fa-wrench<3> <nth_delimiter><B>double<1>msc_command<2>fa fa-mobile<3><nth_delimiter>