2012-05-05 15 views
4

私はboost::spiritを学んでいます。構造体にテキストを読み込んで解析しようとしています。例えば、"2: 4.6"は、下の私のTestStruct2とダブル4.6 intとして解析されboost :: spiritを使ってテキストを構造体に解析するには?

#include <iostream> 
#include <boost/spirit/include/qi.hpp> 
#include <boost/spirit/include/support_istream_iterator.hpp> 
#include <boost/fusion/include/std_pair.hpp> 
namespace qi = boost::spirit::qi; 

struct TestStruct { 
    int myint; 
    double mydouble; 
    TestStruct() {} 
    TestStruct(std::pair<int,double> p) : myint(p.first), mydouble(p.second) {} 
}; 

template <typename Iterator, typename Skipper> 
struct MyGrammar : qi::grammar<Iterator, TestStruct(), Skipper> { 
    MyGrammar() : MyGrammar::base_type(mystruct) { 
    mystruct0 = qi::int_ >> ":" >> qi::double_; 
    mystruct = mystruct0; 
    } 
    qi::rule<Iterator, std::pair<int,double>(), Skipper> mystruct0; 
    qi::rule<Iterator, TestStruct(), Skipper> mystruct; 
}; 

int main() { 
    typedef boost::spirit::istream_iterator It; 
    std::cin.unsetf(std::ios::skipws); 
    It it(std::cin), end; // input example: "2: 3.4"                    

    MyGrammar<It, qi::space_type> gr; 
    TestStruct ts; 
    if (qi::phrase_parse(it, end, gr, qi::space, ts) && it == end) 
    std::cout << ts.myint << ", " << ts.mydouble << std::endl; 
    return 0; 
} 

それはうまく動作しますが、私はこのコードを簡素化することができるどのように思ったんだけど?例えば

、私は自動的にmystructルールからTestStructオブジェクトを構築するために使用されるタイプstd::pair<int,double>をマークするだけでありmystruct0文法規則、取り除くしたいと思います。

可能であれば、コンストラクタをstd::pairから削除したいと考えています。

したがって、次のコードをどうにかしてコンパイルできますか?

struct TestStruct { 
    int myint; 
    double mydouble; 
    TestStruct() {} 
    TestStruct(int i, double d) : myint(i), mydouble(d) {} 
}; 

template <typename Iterator, typename Skipper> 
struct MyGrammar : qi::grammar<Iterator, TestStruct(), Skipper> { 
    MyGrammar() : MyGrammar::base_type(mystruct) { 
    mystruct = qi::int_ >> ":" >> qi::double_; 
    } 
    qi::rule<Iterator, TestStruct(), Skipper> mystruct; 
}; 

int main() { 
    typedef boost::spirit::istream_iterator It; 
    std::cin.unsetf(std::ios::skipws); 
    It it(std::cin), end; // input example: "2: 3.4"                    

    MyGrammar<It, qi::space_type> gr; 
    TestStruct ts; 
    if (qi::phrase_parse(it, end, gr, qi::space, ts) && it == end) 
    std::cout << ts.myint << ", " << ts.mydouble << std::endl; 
    return 0; 
} 

残念ながら、コンパイラは言う:

boost_1_49_0/include/boost/spirit/home/qi/detail/assign_to.hpp:123: 
error: no matching function for call to ‘TestStruct::TestStruct(const int&)’ 

答えて

2

はい、コードをコンパイルできます。実際には、コンストラクタなしで行うことができます:デフォルトの(コンパイラ生成の)コンストラクタは問題ありません。

あなたが必要とするのは、構造体を融合シーケンスとして適合させることだけです。 (ボーナスとして、これはカルマにも同様に働きます)
これは最初にstd::pairを働かせた魔法です。

#include <iostream> 
#include <boost/spirit/include/qi.hpp> 
#include <boost/fusion/adapted/struct.hpp> 
namespace qi = boost::spirit::qi; 

struct TestStruct { 
    int myint; 
    double mydouble; 
}; 

BOOST_FUSION_ADAPT_STRUCT(TestStruct, (int, myint)(double, mydouble)); 

template <typename Iterator, typename Skipper> 
struct MyGrammar : qi::grammar<Iterator, TestStruct(), Skipper> { 
    MyGrammar() : MyGrammar::base_type(mystruct) { 
     mystruct = qi::int_ >> ":" >> qi::double_; 
    } 
    qi::rule<Iterator, TestStruct(), Skipper> mystruct; 
}; 

int main() { 
    typedef std::string::const_iterator It; 
    const std::string input("2: 3.4"); 
    It it(input.begin()), end(input.end()); 

    MyGrammar<It, qi::space_type> gr; 
    TestStruct ts; 

    if (qi::phrase_parse(it, end, gr, qi::space, ts) && it == end) 
     std::cout << ts.myint << ", " << ts.mydouble << std::endl; 

    return 0; 
} 
3

構造体に値「順次」を解析することができるようにするには、あなたがfusionタプルにそれを変換する必要があることは非常に良く解決策になります、hereと記載されている。あなたのケースでは

、これはあなたが

  1. する必要があることを意味融合適応する構造体のマクロを使用し

    #include <boost/fusion/adapted/struct/adapt_struct.hpp> 
    
  2. 必要なヘッダをインクルードします。最高の場所はTestStructの宣言の後:これら二つの変更により

    BOOST_FUSION_ADAPT_STRUCT(
         TestStruct, 
         (int,myint) 
         (double,mydouble) 
        ) 
    

、あなたの簡易版をコンパイルし、望ましい結果が得られます。確かに現実のほうがはるかに簡単であるかどうか確信してください。–しかし、構造体にメンバーを追加する予定がある場合は、将来的に単純化するのに役立つかもしれません。

私は、プログラムを簡単にするために他に大きな変更はありません。

関連する問題