Непоследовательное поведение столбца директивы генератора в повышении кармы

Я пишу генератор кармы для создания HTML-страницы, и я испытываю непоследовательное поведение при использовании директивы столбца. Это вполне может быть моим пониманием того, как это работает.

В основном я создаю сетку, которая требует, чтобы я вставлял некоторые разделители после каждых двух вхождений данных.

Ниже приведена базовая программа, которую я использовал для тестового прогона.

#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;
}

Вышеуказанное генерирует следующий вывод:

<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

Как уже отмечалось, n-й разделитель появляется после каждого поколения, а не каждую секунду.

Ожидаемый результат

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

person user48833    schedule 01.05.2017    source источник
comment
Каков ожидаемый результат   -  person sehe    schedule 01.05.2017
comment
обновленный ответ с комментариями   -  person user48833    schedule 01.05.2017
comment
С columns() вы в любом случае получите конечный nth_delimiter. Так указано.   -  person sehe    schedule 01.05.2017
comment
Пришло время снова обратиться к документации, чтобы выяснить, как этого добиться :(   -  person user48833    schedule 01.05.2017
comment
Я только что опубликовал два подхода с бонусным объяснением того, почему ваши ожидания не оправдались. Надеюсь, поможет.   -  person sehe    schedule 01.05.2017


Ответы (1)


Я думаю, что это близко к тому, чего вы хотите достичь. Как я уже сказал, последний (незавершенный) запуск все равно будет «завершен» тегом nth_delimiter:

Прямой эфир на 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;
}

Отпечатки

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

Бонус:

Проблема с smallbox % eol в том, что smallbox — это элемент, и eol тоже:

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

Прямой эфир на 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>
person sehe    schedule 01.05.2017
comment
Это круто! уже давно пытаюсь разобраться :) - person user48833; 01.05.2017