Использование std :: array в качестве атрибута для boost :: spirit :: x3

Я пытаюсь разобрать список чисел в фиксированный размер std::array контейнер, использующий новейшую версию boost :: spirit x3 (как включено в boost 1.54).
поскольку std::array имеет необходимые функции, он определяется как контейнер, но ему не хватает функции вставки, что делает его несовместимым.
Вот краткий пример того, что я пытаюсь сделать:

#include <boost/spirit/home/x3.hpp>

#include <array>
#include <iostream>
#include <string>

namespace x3 = boost::spirit::x3;
namespace ascii = boost::spirit::x3::ascii;

typedef std::array<double, 3> Vertex;

int main(int, char**) {
using x3::double_;
using ascii::blank;

std::string input = "3.1415 42 23.5";
auto iter = input.begin();

auto vertex = x3::rule<class vertex, Vertex>{} =
double_ >> double_ >> double_;

Vertex v;

bool const res = x3::phrase_parse(iter, input.end(), vertex, blank, v);
if (!res || iter != input.end()) return EXIT_FAILURE;

std::cout << "Match:" << std::endl;
for (auto vi : v) std::cout << vi << std::endl;
return EXIT_SUCCESS;
}

Это не скомпилируется с std::array не имеет insert функция.
В качестве обходного пути я использовал семантические действия:

auto vertex() {
using namespace x3;
return rule<class vertex_id, Vertex>{} =
double_[([](auto &c) { _val(c)[0] = _attr(c); })] >>
double_[([](auto &c) { _val(c)[1] = _attr(c); })] >>
double_[([](auto &c) { _val(c)[2] = _attr(c); })];
}

а затем позвоните

x3::phrase_parse(iter, input.end(), vertex(), blank, v);

вместо. Это работает (используя clang 3.6.0 с -std = c ++ 14), но я думаю, что это решение очень не элегантное и трудно читаемое.

Поэтому я попытался адаптировать std :: array как последовательность слияния, используя BOOST_FUSION_ADAPT_ADT вот так:

BOOST_FUSION_ADAPT_ADT(
Vertex,
(double, double, obj[0], obj[0] = val)
(double, double, obj[1], obj[1] = val)
(double, double, obj[2], obj[2] = val))

а затем специализируется x3::traits::is_container чтобы Vertex сказал x3 не обрабатывать std :: array как контейнер:

namespace boost { namespace spirit { namespace x3 { namespace traits {
template<> struct is_container<Vertex> : public mpl::false_ {};
}}}}

Но это не скомпилируется в сочетании с x3. Это ошибка или я ее неправильно использую?
Звонок, например fusion::front(v) без всего кода x3 компилируется и работает, так что я думаю, что мой код не является полностью неправильным.

Тем не менее, я уверен, что для x3 есть более чистое решение, в котором не используются адаптеры Fusion или семантические действия для этой простой проблемы.

5

Решение

Код, который вы разместили, пронизан ошибочными ошибками. Нет никаких оснований ожидать, что что-то там будет компилироваться, правда.

Несмотря ни на что, я убрал это ». Конечно, вы должны были включить

#include <boost/fusion/adapted/array.hpp>

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

Это проблема юзабилити с Spirit X3, которая все еще находится в экспериментальной фазе. Вы можете сообщить об этом в списке рассылки [spirit-general]. Реакция обычно довольно быстрая.


¹ на случай, если вы захотите увидеть, с чем я работал http://paste.ubuntu.com/12764268/; Я также использовал x3::repeat(3)[x3::double_] для сравнения.

0

Другие решения

Других решений пока нет …

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector