2015-10-12 9 views
5

boost :: spiritの最新リリースx3(boost 1.54に含まれています)を使用して固定サイズのstd::arrayコンテナに数値のリストを解析しようとしています。 std::arrayには必要な機能があるため、コンテナとして検出されますが、挿入機能がないため互換性がありません。ここ は、私が達成しようとしているものの短い例です:boost :: spirit :: x3の属性として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 ::配列を処理しないようにX3を伝えるために頂点のためのx3::traits::is_containerを専門に、その後

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)) 

と::

は、だから私は BOOST_FUSION_ADAPT_ADTそう等を用いて融合配列としてのstd ::配列を適応しようとした

namespace boost { namespace spirit { namespace x3 { namespace traits { 
    template<> struct is_container<Vertex> : public mpl::false_ {}; 
}}}} 

しかし、これはx3と組み合わせてコンパイルされません。これはバグですか、私は間違って使っていますか? fusion::front(v)すべてのx3コードがコンパイルされずに動作するので、私のコードは完全に間違っているとは思わない。

しかし、この単純な問題では、融合アダプタやセマンティックアクションを含まないx3のクリーナーソリューションがあると確信しています。

+0

'boost :: array'はオプションですか?私は、 "boost/fusion/include/boost_array.hpp"、 "double_ >> double_ >> double_'などは動作するはずです。 – llonesmiz

+0

私はそれらの愚かなエラーを修正しました。申し訳ありません。 'boost :: array'は、' std :: array'に大きく依存する既存のコードをインターフェースしているので、オプションではありません。 – ithron

+0

あなたのアプローチをコンパイルするために[これはひどいハックです](http://coliru.stacked-crooked.com/a/412c97fecfa4e4b1)。あなたはおそらくより良い答え(または実際には良いもの)を待つべきです。 – llonesmiz

答えて

0

あなたが投稿したコードは、間違ったエラーで詰まっています。実際にコンパイルするには何かを期待する必要はありません。

それにかかわらず、私はそれを清潔にしました。もちろん、あなたが含まれているはずです

#include <boost/fusion/adapted/array.hpp> 

悲しいかさ、それは単にうまくいきません。私は(あなたがそれについて読んで前にあなたが言及したのと同じことを試した後に:))とほぼ同じ結論に達しました。

これはSpirit X3のユーザビリティの問題です。まだ実験段階です。あなたは[spirit-general]メーリングリストで報告することができます。応答は通常かなり迅速です。


1私がhttp://paste.ubuntu.com/12764268/で働いていたことを確認したい場合は、比較のためにx3::repeat(3)[x3::double_]も使用しました。

+0

残念ながら 'std :: array'は融合によって適合されていません。あなたが提案するヘッダー(または "boost/fusion/include/boost_array.hpp")は 'boost :: array'にのみ影響します。 [これは](http://coliru.stacked-crooked.com/a/07416373f7d19da3)いくつかの小さな変更で動作するようです。 [Here](https://svn.boost.org/trac/boost/ticket/8241)は、 'std :: array'を適応させる非常に古い試みです(まだ動作しているかどうかはわかりません)。 – llonesmiz

+0

hh。私のためにも、それはブーストアレイの価値がありませんでした。私は後で時間があるときの違いを見ていきます。 – sehe

+1

'std :: forward_list'にも同様の問題があります。 Boost.Spiritに関して、クラスがコンテナであるために必要な 'push_back'。 – Orient

関連する問題