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);
代わりは。これは機能しますが (-std=c++14 で clang 3.6.0 を使用)、このソリューションは非常に洗練されておらず、読みにくいと思います。
BOOST_FUSION_ADAPT_ADT
だから私は std::array を次のように使用して融合シーケンスとして適応させようとしました:
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))
次に Vertex を特殊化x3::traits::is_container
して x3 に std::array をコンテナーとして扱わないように指示します。
namespace boost { namespace spirit { namespace x3 { namespace traits {
template<> struct is_container<Vertex> : public mpl::false_ {};
}}}}
ただし、これは x3 と組み合わせてコンパイルすることはできません。これはバグですか、それとも使い方が間違っていますか? たとえば、すべての x3 コードなしで呼び出すfusion::front(v)
と、コンパイルして機能するので、コードが完全に間違っているわけではないと思います。
ただし、この単純な問題に対するフュージョン アダプターやセマンティック アクションを含まない x3 を使用した、よりクリーンなソリューションがあると確信しています。