Parsing vectors of shared_ptr to base class
Mario Lang <[email protected]>
| Newsgroups | gmane.comp.parsers.spirit.general |
|---|---|
| Message-ID | <[email protected]> |
Hi.
I just realized I can parse heterogenous containers of pointers to base
classes with something like this:
#if !defined(BMML_SPIRIT_X3_HPP)
#define BMML_SPIRIT_X3_HPP
#include <boost/spirit/home/x3.hpp>
namespace bmml {
namespace spirit {
inline namespace x3 {
template<typename T>
struct dynamic_pointer_parser : boost::spirit::x3::parser<
dynamic_pointer_parser<T>
> {
using attribute_type = std::shared_ptr<T>;
template < typename Iterator, typename Context, typename RContext
, typename Attribute>
bool parse( Iterator& first, Iterator const& last
, Context const& context, RContext& rcontext
, Attribute& attr) const {
if (auto val = std::dynamic_pointer_cast<T>(*first)) {
boost::spirit::x3::traits::move_to(val, attr);
++first;
return true;
}
return false;
}
};
template <typename T> dynamic_pointer_parser<T> shared_ptr = {};
}
}
}
#endif // !defined(BMML_SPIRIT_X3_HPP)
A small use case might look like this:
#include <fstream>
#include <iostream>
#include <x3.hpp>
#include <bmml.hxx>
using std::begin;
using std::cout;
using bmml::dom::element;
using std::end;
using std::endl;
using bmml::generic_text;
using std::ifstream;
using bmml::newline;
using bmml::spirit::shared_ptr;
using bmml::space;
using std::vector;
namespace x3 = boost::spirit::x3;
int main(int argc, char *argv[]) {
ifstream file(argv[1]);
auto score = bmml::parse(file, argv[1]);
if (auto score_data = score->data()) {
vector<std::shared_ptr<element>> text;
auto iter = begin(*score_data);
if (x3::parse(iter, end(*score_data),
*(shared_ptr<space> | shared_ptr<newline> | shared_ptr<generic_text>),
text)) {
cout << text.size() << " text elements at beginning." << endl;
}
}
}
This is going to save me a lot of icky nested conditionals and casts.
And has quite some potential. I am going to use it a lot with operator%
to parse a nested vector of things separated by specific spearators.
Something I wouldn't want to write with imperative code.
But with this wrapping, spirit can do all the magic.
I wonder if this could be made generic enough to be put into X3 / if
something like this would be useful to others?
Any suggestions for better naming? I wonder if attribute_type can be
defined properly?
decltype(std::dynamic_pointer_cast<T>(*std::declval<Iterator>())) can
not work because Iterator is not known.
Besides, it does all what I want already. I can parse casted pointers
into adapted structs, and it will happily do the right thing if
operator| is used on a vector of shared_ptr to a common base.
--
CYa,
⡍⠁⠗⠊⠕
------------------------------------------------------------------------------
Transform Data into Opportunity.
Accelerate data analysis in your applications with
Intel Data Analytics Acceleration Library.
Click to learn more.
http://pubads.g.doubleclick.net/gampad/clk?id=278785231&iu=/4140
_______________________________________________
Spirit-general mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/spirit-general