Как сгенерировать карму повышения в массив С++?

Я вижу, как можно использовать карму для создания контейнера, управляющего памятью, например std::string. Но как насчет случая, когда буфер (char[N]) был предварительно выделен?

  {
    using namespace boost::spirit::karma;
    {
      std::string buffer;
      generate(std::inserter(buffer, buffer.begin()), double_, 3.13);
      std::cout << ':' << buffer << ':' << std::endl;
    }
    {
      //////////////////////////////////////////////////////////////////////
      // How to make the following work? Is there a builtin output
      // iterator that just works?
#if defined(MAJIC)
      char buffer[1024];
      generate(buffer, double_, 3.13);
      std::cout << ':' << buffer << ':' << std::endl;
#endif
    }
  }

Я хотел бы найти способ разобрать двойник на адрес существующего буфера. Можно предположить, что буфер достаточно велик для этого случая. Может быть, основной вопрос действительно заключается в том, есть ли уже адаптер выходного итератора или что-то в карме для собственных массивов, которые можно было бы использовать?


person user1338952    schedule 30.09.2015    source источник


Ответы (1)


API на основе итератора Karma (здесь) принимает... итераторы вывода.

Вы можете просто создать один для вас массив.

Проблема в том, что вам нужно быть очень уверенным в том, что емкость буфера никогда не будет недостаточной:

    char buffer[1024];
    char* it = buffer;
    karma::generate(it, karma::double_ << karma::eol, 3.13);

    std::cout.write(buffer, std::distance(buffer, it));

Обратите внимание, что вы не можете предположить, что буфер завершается NUL. Используйте сгенерированный размер.

Безопасное использование array_sink:

В Boost Iostreams есть более удобный, более общий подход, который также безопасен перед лицом буферов фиксированного размера:

    char buffer[310];
    io::stream<io::array_sink> as(buffer);
    boost::spirit::ostream_iterator it(as);

Вот живая демонстрация, демонстрирующая характеристики:

Жить на Coliru

#include <boost/spirit/include/karma.hpp>
#include <boost/iostreams/device/array.hpp>
#include <boost/iostreams/stream.hpp>

namespace karma = boost::spirit::karma;
namespace io    = boost::iostreams;

void test(std::vector<int> const& v) 
{
    char buffer[310];
    io::stream<io::array_sink> as(buffer);
    boost::spirit::ostream_iterator it(as);

    using namespace karma;
    if (generate(it, int_ % ", " << eol, v))
    {
        std::cout << "Success: ";
        std::cout.write(buffer, as.tellp());
    } else
        std::cout << "Generation failed (insufficient capacity?)\n";
}

int main() {

    std::cout << "Should be ok: \n";
    std::vector<int> v(100, 1);
    test(v);

    std::cout << "This will exceed buffer capacity: \n";
    std::iota(v.begin(), v.end(), 42);
    test(v);
}

Какие печатает

Should be ok: 
Success: 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
This will exceed buffer capacity: 
Generation failed (insufficient capacity?)
person sehe    schedule 30.09.2015
comment
записана прямая трансляция (после ~5 минут) (эксперимент) - person sehe; 01.10.2015
comment
Могу ли я связаться с вами в автономном режиме? У меня есть общий вопрос о применимости Boost Karma к ситуации, в которой я сталкиваюсь (и для которой Q не совсем соответствует шаблону stackoverflow). - person ForeverLearning; 02.06.2016
comment
Я обратился к этому с помощью @, но по какой-то причине SO не отображает его, особенно учитывая, что вы сделали одинокий комментарий к своему сообщению. - person ForeverLearning; 02.06.2016
comment
Спасибо за совет array_sink! - person Chris Beck; 05.04.2018
comment
@sehe Вы знаете, как это на самом деле работает под капотом? Я смотрю на boost::spirit::ostream_iterator, я предполагаю, что карма обнаруживает, что буфер исчерпан из-за аксессора good здесь: github.com/boostorg/spirit/blob/develop/include/boost/spirit/ Таким образом, карма на самом деле является более общей, чем просто получение OutputIterator, он будет использовать функцию-член good, если она доступна, чтобы проверить, действителен ли выходной итератор? - person Chris Beck; 05.04.2018
comment
Я думаю, что подробности здесь на самом деле, теперь это имеет смысл: github.com/boostorg/spirit/blob/develop/include/boost/spirit/ - person Chris Beck; 05.04.2018