Sto cercando di analizzare un elenco di numeri in un contenitore std::array
di dimensioni fisse utilizzando la versione più recente di boost :: spirit x3 (inclusa in boost 1.54). Poiché std::array
ha le funzioni necessarie, viene rilevato come contenitore, ma manca la funzione di inserimento che lo rende incompatibile. Ecco un breve esempio di quello che sto cercando di realizzare:Utilizzo di std :: array come attributo per 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;
}
Questo non verrà compilato dal std::array
ha alcuna funzione insert
. Come una soluzione che ho usato azioni semantiche:
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); })];
}
e quindi chiamare
x3::phrase_parse(iter, input.end(), vertex(), blank, v);
invece. Funziona (usando clang 3.6.0 con -std = C++ 14), ma penso che questa soluzione sia molto poco elegante e difficile da leggere.
Così ho cercato di adattare std :: array come una sequenza di fusione utilizzando BOOST_FUSION_ADAPT_ADT
in questo modo:
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))
e poi specializzandosi x3::traits::is_container
per Vertex per dire x3 di non trattare std :: array come un contenitore:
namespace boost { namespace spirit { namespace x3 { namespace traits {
template<> struct is_container<Vertex> : public mpl::false_ {};
}}}}
Ma questo non verrà compilato in combinazione con x3. È un bug o lo sto usando male? Chiamando ad es. fusion::front(v)
senza che tutto il codice x3 compili e funzioni, quindi suppongo che il mio codice non sia completamente sbagliato.
Tuttavia sono sicuro che c'è una soluzione più pulita con x3 che non coinvolge adattatori di fusione o azioni semantiche per questo semplice problema.
È 'boost :: array' un'opzione? Credo che includere "boost/fusion/include/boost_array.hpp" 'double_ >> double_ >> double_' dovrebbe funzionare. – llonesmiz
Ho corretto quegli errori stupidi, mi dispiace per quello. 'boost :: array' non è un'opzione dal momento che sto interagendo con il codice esistente che fa molto affidamento su' std :: array'. – ithron
[Questo è un trucco terribile] (http://coliru.stacked-crooked.com/a/412c97fecfa4e4b1) per rendere il tuo approccio compilato. Probabilmente dovresti aspettare una risposta migliore (o effettivamente una buona risposta). – llonesmiz