Учитывая мой случай, каркас для решения, или, скорее, обходной путь, просто играющий с частями, которые действительно легко работают в boost.spirit:
namespace X {
struct p { double t,v;};// point, time, value
struct ts { // simplified time-series representation, time-axis computed
bool s;
double t0,dt;size_t n;// ti = t0 + dt*i
std::vector<double> v;// v.size()===n
p point(size_t i ) const { return p{t0+dt*i,v[i]};}
};
//--would like to output grammar like {pfx:(true|false),data:[[t,v]..]}
//--; first construct a container class out of ts, using boost iterator_facade
//--; to get away with few lines.(simplified..)
struct ts_c {
using value_type=p;// iterate over (t,v), t is computed, v is plain vector
ts * c;
struct iterator:public::boost::iterator_facade<iterator,p,boost::random_access_traversal..> { //..
iterator(ts*c,size_t pos=0u):c{c},pos{pos} {}
//.. plain vanilla impl. goes here according to boost::iterator_facade.
private:
ts* c;
size_t pos;
};
using const_iterator=iterator;
iterator begin() const;//.. etc. impl. of need it stuff.
};
}
// use FUSION to adapt the ts-type, let last tuple member return the
// tuple members:
// 0 true if n>0, otherwise false
// 1 true if ts.s is true
// 2 returns a vanilla iterable container, ts_c exposing type p
BOOST_FUSION_ADAPT_ADT(
X::ts,
(bool,bool, obj.n>0,/**/)
(bool,bool,obj.s,/**/)
(X::ts_c,X::ts_c, X::ts_c(&obj),/**/)
)
//-- then combining the boost spirit complex example to emit the point class p
namespace X {
namespace ka=boost::spirit::karma;
/** generate a point like [123.0, 3.14], or [123.0,null] if !isfinite.
* using the complex example pattern given in boost::spirit,
*/
template<class OutputIterator>
struct point_generator:ka::grammar<OutputIterator,p()> {
point_generator():point_generator::base_type(pg) {
using ka::true_;
using ka::bool_;
using ka::omit;
pg =
&true_ <<( '[' << double_<< ',' << double_ << ']')
|
omit[bool_]<< ( '[' << double_<< ',' << "null" << ']')
;
}
ka::rule<OutputIterator,p()> pg;
};
/** @brief a ts generator
*
* outputs:
* {pfx:(true|false),data:[[t,v],..]}
* or if empty
* {pfx:null,data:null}
*/
template<class OutputIterator>
struct ts_generator:ka::grammar<OutputIterator,ts()> {
ts_generator():ts_generator::base_type(tsg) {
using ka::true_;
using ka::bool_;
using ka::omit;
tsg =
&true_ <<"{pfx:"<<bool_<<",data:"<<( '[' << pt_ % ',' << ']')<<'}'
|
omit[bool_]<< "{pfx:null: data:null}"
;
}
ka::rule<OutputIterator,ts()> tsg;
point_generator<OutputIterator> pt_;
};
}