#include #include #include #include #include #include #include #include namespace client { struct A { }; struct B { }; struct C { }; typedef boost::make_variant_over< boost::mpl::vector< A, B, C > >::type component; typedef std::vector components_type; struct foo { components_type components; A a; std::vector pod_vec; }; } namespace tools { namespace mpl = boost::mpl; // no idea, why there is no is_variant in boost template struct is_variant : boost::mpl::false_ { }; template struct is_variant > : boost::mpl::true_ { }; // void visit(visitor, variant) template inline typename boost::enable_if< mpl::and_< is_variant, boost::is_void >, void >::type visit(VisitorT& visitor, VisitableT const& visitable) { std::cout << "\nvisit::variant\n"; boost::apply_visitor(visitor, visitable); } // void visit(visitor, T) template inline typename boost::enable_if< mpl::and_< mpl::not_ >, mpl::not_ >, boost::is_void >, void >::type visit(VisitorT& visitor, VisitableT const& visitable) { std::cout << "\nvisit::T\n"; visitor(visitable); } // void visit(visitor, range) template inline typename boost::enable_if< mpl::and_< boost::has_range_const_iterator, mpl::not_ >, boost::is_void >, void >::type visit(VisitorT& visitor, VisitableT const& visitable) { std::cout << "\nvisit::range\n"; for(auto const& obj : visitable) { visitor(obj); } } // void visit(visitor, range>) template inline typename boost::enable_if< mpl::and_< boost::has_range_const_iterator, is_variant, boost::is_void >, void >::type visit(VisitorT& visitor, VisitableT const& visitable) { std::cout << "\nvisit::range\n"; for(auto const& obj : visitable) { boost::apply_visitor(visitor, obj); } } } template struct visitor : boost::static_visitor { visitor(OStreamT& os) : os(os) { } void operator()(client::foo const& foo) const { os << "Foo:"; tools::visit(*this, foo.components); tools::visit(*this, foo.a); tools::visit(*this, foo.pod_vec); os << "\n"; } void operator()(client::A const&) const { os << 'A'; } void operator()(client::B const&) const { os << 'B'; } void operator()(client::C const&) const { os << 'C'; } void operator()(int) const { os << 'i'; } OStreamT& os; }; void print_all(client::foo const& foo) { visitor v(std::cout); v(foo); } int main() { client::foo foo; foo.components.push_back(client::A()); foo.components.push_back(client::B()); foo.components.push_back(client::C()); foo.pod_vec.push_back(1); foo.pod_vec.push_back(2); foo.pod_vec.push_back(3); print_all(foo); std::cout << '\n'; }