Я пытаюсь разобрать список чисел в контейнер с фиксированным размером std::array
с использованием новейшего релиза boost :: spirit x3 (как указано в boost 1.54). Поскольку std::array
имеет необходимые функции, он определяется как контейнер, но в нем отсутствует функция вставки, что делает ее несовместимой. Вот небольшой пример того, что я пытаюсь сделать:Использование std :: array as Attribute for boost :: spirit :: x3
#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), но я думаю, что это решение очень неэлегантно и трудно читается.
Так что я пытался адаптировать зЬй :: массива в виде последовательности слитой с использованием 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 не лечить зЬй :: массива в качестве контейнера:
namespace boost { namespace spirit { namespace x3 { namespace traits {
template<> struct is_container<Vertex> : public mpl::false_ {};
}}}}
Но это не будет компилироваться в сочетании с x3. Является ли это ошибкой или я неправильно ее использую? Вызов, например. fusion::front(v)
без кода x3 компилируется и работает, поэтому я предполагаю, что мой код не совсем ошибочен.
Однако я уверен, что есть более чистое решение с x3, не связанное с адаптерами или семантическими действиями для этой простой проблемы.
Является ли 'boost :: array' опцией? Я считаю, что «boost/fusion/include/boost_array.hpp» «double_ >> double_ >> double_' должен работать. – llonesmiz
Я исправил эти глупые ошибки, извините за это. 'boost :: array' не является параметром, так как я взаимодействую с существующим кодом, который в значительной степени зависит от' std :: array'. – ithron
[Это ужасный хак] (http://coliru.stacked-crooked.com/a/412c97fecfa4e4b1), чтобы ваш подход скомпилировался. Вероятно, вам стоит подождать лучшего ответа (или действительно хорошего). – llonesmiz