その後、調べた限りでは、spirit::qiは、boost::variantと併用されることが結構ある。
なぜか。
1つには、複数の型(int, double, bool..)を持つ入力を処理することがあるためである。
コードを見てみる。。。
1#include <boost/spirit/include/qi.hpp>
2#include <boost/variant.hpp>
3#include <string>
4#include <vector>
5#include <iostream>
6
7using namespace boost::spirit;
8
9template <typename Iterator, typename Skipper>
10struct QI_grammar : qi::grammar<Iterator,
11 std::vector<boost::variant<int, bool>>(), Skipper>
12{
13 QI_grammar() : QI_grammar::base_type{values}
14 {
15 value = qi::int_ | qi::bool_;
16 values = value % ',';
17 }
18
19 qi::rule<Iterator, boost::variant<int, bool>(), Skipper> value;
20 qi::rule<Iterator, std::vector<boost::variant<int, bool>>(), Skipper>
21 values;
22};
23
24struct display : public boost::static_visitor<>
25{
26 template <typename T>
27 void operator()(T t) const
28 {
29 std::cout << std::boolalpha << t << ';';
30 }
31};
32
33int main()
34{
35 std::string s;
36 std::getline(std::cin, s);
37 auto it = s.begin();
38 QI_grammar<std::string::iterator, ascii::space_type> g;
39 std::vector<boost::variant<int, bool>> v;
40 if (qi::phrase_parse(it, s.end(), g, ascii::space, v))
41 {
42 for (const auto &elem : v)
43 boost::apply_visitor(display{}, elem);
44 }
45}
ここで、13-21行目に注目する。
+c++ 13 QI_grammar() : QI_grammar::base_type{values} 14 { 15 value = qi::int_ | qi::bool_; 16 values = value % ','; 17 } 18 19 qi::rule<Iterator, boost::variant<int, bool>(), Skipper> value; 20 qi::rule<Iterator, std::vector<boost::variant<int, bool>>(), Skipper> 21 values; +
15行目で、intかbool型をパースするルールを定義し、19行目でそれを受けている。
19行目で、boost::variantを使っている。
+c++ 15 value = qi::int_ | qi::bool_; 19 qi::rule<Iterator, boost::variant<int, bool>(), Skipper> value; +
boost::variantにはいろいろな説明があるが、捉え方としては「複数の型を持つタプル」というアイディアがある。
実行してみる。。。
$ ./a.out
false
false;
$ ./a.out
string
$ ./a.out
1,true,2,false,3,wrongString,4,true
1;
true;
2;
false;
3;
intとbool型だけ受け付けているのがわかる。(`ー´)b