0%

在Spirit Qi中使用std::shared_ptr对象

boost::spirit::qi是一个用于解析字符串的库,可以用于解析字符串并构造对象。在解析的过程中,有时候需要构造语法树,这个时候通常可以采用phx::new_或者phx::construct来构造裸指针或对象。但是在实际的应用当中,有时候会希望通过如std::shared_ptr这样的智能指针来管理对象的生命周期,但是在boost::phoenix当中并没有提供make_shared这样的函数对象。

基于stackoverflow上的回答可以构造一个make_shared_的函数对象,用于在boost::spirit::qi的语法规则当中延迟构造std::shared_ptr对象。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
namespace boost::phoenix {
template <typename T>
struct make_shared_f {
template <typename... A>
struct result {
typedef std::shared_ptr<T> type;
};

template <typename... A>
typename result<A...>::type operator()(A&&... a) const {
return std::make_shared<T>(std::forward<A>(a)...);
}
};
template <typename T>
using make_shared_ = function<make_shared_f<T>>;
} // namespace boost::phoenix

在使用的时候可以如下构造创建std::shared_ptr对象的action:

1
2
3
4
5
6
7
8
9
10
11
12
namespace qi = boost::spirit::qi;
namespace phx = boost::phoenix;

using phx::make_shared_;
using qi::_1;
using qi::_val;

...

expr = term[_val = _1] >>
*(('+' >> term[_val = make_shared_<AddNode>()(_val, _1)]) |
('-' >> term[_val = make_shared_<SubNode>()(_val, _1)]));