Я пытаюсь разобрать список чисел в фиксированный размер 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 или семантические действия для этой простой проблемы.
Код, который вы разместили, пронизан ошибочными ошибками. Нет никаких оснований ожидать, что что-то там будет компилироваться, правда.
Несмотря ни на что, я убрал это ». Конечно, вы должны были включить
#include <boost/fusion/adapted/array.hpp>
К сожалению, это просто не работает. Я пришел к тому же самому заключению (попробовав то же самое, что вы упомянули, прежде чем прочитать об этом :)).
Это проблема юзабилити с Spirit X3, которая все еще находится в экспериментальной фазе. Вы можете сообщить об этом в списке рассылки [spirit-general]. Реакция обычно довольно быстрая.
¹ на случай, если вы захотите увидеть, с чем я работал http://paste.ubuntu.com/12764268/; Я также использовал x3::repeat(3)[x3::double_]
для сравнения.
Других решений пока нет …