J'essaye d'analyser une liste de nombres dans un conteneur de taille fixe std::array
en utilisant la version la plus récente de boost :: spirit x3 (incluse dans boost 1.54). Depuis std::array
a les fonctions nécessaires, il est détecté comme un conteneur, mais il lui manque la fonction d'insertion qui le rend incompatible. Voici un court exemple de ce que je suis en train d'accomplir:Utilisation de std :: array comme attribut pour 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;
}
Ce ne sera pas compilé depuis std::array
n'a aucune fonction insert
. Pour contourner ce problème je les actions sémantiques:
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); })];
}
puis appelez
x3::phrase_parse(iter, input.end(), vertex(), blank, v);
à la place. Cela fonctionne (en utilisant clang 3.6.0 avec -std = C++ 14), mais je pense que cette solution est très inélégante et difficile à lire.
J'ai donc essayé d'adapter std :: tableau comme une séquence de fusion en utilisant BOOST_FUSION_ADAPT_ADT
comme ceci:
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))
puis spécialisée x3::traits::is_container
pour Vertex de dire x3 de ne pas traiter std :: tableau comme un conteneur:
namespace boost { namespace spirit { namespace x3 { namespace traits {
template<> struct is_container<Vertex> : public mpl::false_ {};
}}}}
Mais cela ne compilera pas en combinaison avec x3. Est-ce un bug ou est-ce que je l'utilise mal? L'appel par ex. fusion::front(v)
sans tout le code x3 compile et fonctionne, donc je suppose que mon code n'est pas complètement faux.
Cependant, je suis sûr qu'il existe une solution plus propre avec x3 n'impliquant pas d'adaptateurs de fusion ou d'actions sémantiques pour ce problème simple.
Est-ce que 'boost :: array' est une option? Je crois y compris "boost/fusion/include/boost_array.hpp" 'double_ >> double_ >> double_' devrait fonctionner. – llonesmiz
J'ai corrigé ces erreurs stupides, désolé pour ça. 'boost :: array' n'est pas une option car j'interface un code existant qui repose fortement sur' std :: array'. – ithron
[Ceci est un hack terrible] (http://coliru.stacked-crooked.com/a/412c97fecfa4e4b1) pour rendre votre approche compilée. Vous devriez probablement attendre une meilleure réponse (ou en fait une bonne réponse). – llonesmiz