recursion - C++ Boost recursive variant overloading apply_visitor -
abstract: looking overload apply_visitor() method in class contains recursive boost::variant object.
in code included below there method:
template <typename t> ostream& apply_visitor(const t& fn) const i overload method different visitors. this:
ostream& apply_visitor(const printdata& fn) const but problem class printdata not yet complete (see comments in code below). defined after node class. have 2 questions (among others -- welcome general critique on code modeling i'd put production).
1) there way apply_visitor(printdata&) work?
2) can rearrange (recursive) variant visitor methods in printdata , wouldn't have add apply_visitor node class?
/** * compiled gcc (tested 4.7.2 on linux) * requires boost development headers discoverable * compiler. * * g++ -otest-recursive-visit -std=c++11 test-recursive-visit.cpp * ./test-recursive-visit **/ #include <iostream> #include <map> #include <string> #include <vector> #include "boost/variant.hpp" #include "boost/variant/recursive_wrapper.hpp" #include "boost/variant/static_visitor.hpp" using namespace std; /// type name demangler (as implemented in g++). other compilers, /// add more #elif statements, now, return /// mangled name. #ifdef __gnug__ /// compiler g++ #include <cxxabi.h> string type_demangle(const string& name) { int status; char* res = abi::__cxa_demangle( name.c_str(), null, null, &status); string demangled_name((status==0) ? res : name); free(res); return demangled_name; } #else /// compiler not g++ string type_demangle(const string& name) { return name; } #endif /// forward declaration of node class /// (needed recursive variant type) class node; /// actual recursive variant type /// (typically hidden users) typedef boost::variant< boost::recursive_wrapper<node>, vector<int>, vector<float> > data_t; // forward declaration printdata. see note below concerning // node::apply_visitor() class printdata; /// object users see /// prototyping, tree object public class node { public: /// sub-nodes identified unique strings /// point 1 of objects data_t /// can hold map<string,data_t> tree; /// constructor std::map object, passed tree node(const initializer_list<pair<const string,data_t>>& l) : tree(l) {} // // interesting part of example here // // tried replace t& printdata& adding // forward declaration @ top // errors: // // line 86: // invalid use of incomplete type ‘const class printdata’ // line 53: // forward declaration of ‘const class printdata’ // /// called boost::apply_visitor(visitor(),node) //ostream& apply_visitor(const printdata& fn) const template <typename t> ostream& apply_visitor(const t& fn) const { (auto : tree) { *fn.os << fn.prefix << i.first; i.second.apply_visitor(fn); } return *fn.os; } }; /// printing visitor ostream object class printdata : public boost::static_visitor<ostream&> { public: ostream* os; string prefix; /// keep pointer ostream , keep /// prefix string hold , "indent" /// " " every level /// of recursion printdata(ostream& out_stream, const string& prefix_str="") : os(&out_stream) , prefix(prefix_str) {} /// recurse tree, adding indent characters prefix ostream& operator()(node& n) const { *os << endl; n.apply_visitor(printdata(*os, prefix+" ")); *os; } /// actual data types want print out template <typename t> ostream& operator()(const vector<t>& d) const { *os << " (vector<" << type_demangle(typeid(t).name()) << ">):"; (t : d) { *os << " " << i; } *os << endl; return *os; } }; /// convenience operator allow: cout << node; ostream& operator<<(ostream& os, const node& n) { return boost::apply_visitor(printdata(os), n); } int main() { /// hooray initialization lists!!! node n { {"x", node{ {"a", vector<int>{1,2,3}}, {"b", vector<float>{2,3,4}} }}, {"y", vector<int>{3,4,5}}, {"z", node{ {"a", node{ {"c", vector<float>{4,5,6}} }} }} }; /** applying printdata n prints out following: x (vector<int>): 1 2 3 b (vector<float>): 2 3 4 y (vector<int>): 3 4 5 z c (vector<float>): 4 5 6 **/ cout << n; }
declare function, don't define inside class. instead, wait define until after you've defined printdata, @ point complete type.
class printdata; class node { public: ... ostream& apply_visitor(const printdata& fn) const; ... }; class printdata : public boost::static_visitor<ostream&> { ... }; inline ostream& node::apply_visitor(const printdata& fn) const { ... }
Comments
Post a Comment