c++ - Derive from `boost::static-visitor` to remove code duplication -


in 1 of projects i'm using boost-variant excessively. @ point exceeded maximum number of template parameters (20) boost-variant. hence, derived following solution linking several boost-variant types linked-list.

#include <boost/variant.hpp> #include <iostream>  template<int t> struct {     const int value = t; };  typedef boost::variant<     a<20>,a<21>,a<22>,a<23>,a<24>,a<25>,a<26>,a<27>,a<28>,a<29>,a<30>,a<31>,a<32>,a<33>,a<34>,a<35>,a<36>,a<37>,a<38>,a<39> > nextvar;  typedef boost::variant<     a<1>,a<2>,a<3>,a<4>,a<5>,a<6>,a<7>,a<8>,a<9>,a<10>,a<11>,a<12>,a<13>,a<14>,a<15>,a<16>,a<17>,a<18>,a<19>,nextvar > tvar;  struct printvisitor : public boost::static_visitor<std::string> {     result_type operator()(const nextvar& n) {         return n.apply_visitor(*this);     }      template<int t>     result_type operator()(const a<t>& a)  {         return std::to_string(a.value);     } };  struct intvisitor : public boost::static_visitor<int> {     result_type operator()(const nextvar& n) {         return n.apply_visitor(*this);     }      template<int t>     result_type operator()(const a<t>& a) {         return a.value;     } };  template<int i> struct addvisitor : public boost::static_visitor<int> {     result_type operator()(const nextvar& n) {         return n.apply_visitor(*this);     }      template<int t>     result_type operator()(const a<t>& a) {         return a.value+i;     } };  int main(int argc, char **args) {     tvar x = a<35>();      printvisitor v1;     std::cout << x.apply_visitor(v1) << std::endl;     intvisitor v2;     std::cout << x.apply_visitor(v2) << std::endl;     addvisitor<10> v3;     std::cout << x.apply_visitor(v3) << std::endl; } 

i surprised how workaround solved problem. still there grain of salt. every visitor had include line:

result_type operator()(const nextvar& n) {     return n.apply_visitor(*this); } 

which seems kind of unnecessary code duplication. getting worse, if i'm in need of 60 or more types in boost-variant. try define common base class of visitors:

template<typename t> struct basevisitor : public boost::static_visitor<t> {     result_type operator()(const nextvar& n) {         return n.apply_visitor(*this);     } }; 

i thought, deriving basevisitor shown below solve problem:

struct printvisitor : public basevisitor<std::string> {     template<int t>     result_type operator()(const a<t>& a)  {         return std::to_string(a.value);     } }; 

but instead compiler complains:

template-argument "const a<t> &" not derived "t19"  

what might closest workaround kind of problem?

first of all, increase limit of 20 fixed boost_mpl_limit_list_size.

about code: if compiles, basevisitor::operator() make infinite recursion besause of *this considered basevisitor @ moment.
avoid that, can use crtp have derived() instead:

template<class derived, typename t> struct basevisitor : public boost::static_visitor<t> {     using typename boost::static_visitor<t>::result_type;      derived & derived() { return static_cast<derived &>(*this); }       result_type operator()(const nextvar& n) {         return n.apply_visitor( derived() );     } }; 

then bringing same operator() scope (otherwise hidden new one) of derived classes (as result_type needed template classes).

demo

without aliases

as said in comments, aliases have written in each derived class. rid of it, can gather 2 operator()s @ same level in base class, , name derived function differently (visit here):

template<class derived, typename t> struct basevisitor : public boost::static_visitor<t> {     using typename boost::static_visitor<t>::result_type;      derived & derived() { return static_cast<derived &>(*this); }       result_type operator()(const nextvar& n) {         return n.apply_visitor( derived() );     }     template<int i>     result_type operator()(const a<i>& a)  {         return derived().visit(a);     } }; 

leaving with:

struct printvisitor : public basevisitor<printvisitor, std::string> {     template<int i>     std::string visit(const a<i>& a)  {         return std::to_string(a.value);     } }; 

demo


Comments

Popular posts from this blog

commonjs - How to write a typescript definition file for a node module that exports a function? -

openid - Okta: Failed to get authorization code through API call -

thorough guide for profiling racket code -