
2012/5/30 Steven Watanabe <watanabesj@gmail.com>
template<class T = _self> struct printable { static void apply(const T& t, std::ostream& os, const std::vector<int>& v) { t.print(os, v); } };
namespace boost { namespace type_erasure { template<class T, class Base> struct concept_interface< ::printable<T>, Base, T> : Base { void print(std::ostream& os, const std::vector<int>& v) const { call(printable<T>(), *this, os, v); } }; }}
The two differences in usage are that you have to use printable<> and printer.print(std::cout, test).
Amazing !! That's a lot less code that I would have imagine. It maybe even could be generate with some macro ? Just a note, with MSVC11 beta I also had to add the concept copy_constructible<> to be able to put my any<mpl::vector<printable<>, copy_constructible<>>> in a std::vector. If others are interested, here is the complete, working code : ------------------------------------- #include <iostream> #include <vector> #include <boost/type_erasure/any.hpp> #include <boost/type_erasure/iterator.hpp> #include <boost/type_erasure/operators.hpp> #include <boost/type_erasure/tuple.hpp> #include <boost/type_erasure/same_type.hpp> #include <boost/mpl/vector.hpp> namespace mpl = boost::mpl; using namespace boost::type_erasure; template<class T = _self> struct printable { static void apply(const T& t, std::ostream& os, const std::vector<int>& v) { t.print(os, v); } }; namespace boost { namespace type_erasure { template<class T, class Base> struct concept_interface< ::printable<T>, Base, T> : Base { void print(std::ostream& os, const std::vector<int>& v) const { call(printable<T>(), *this, os, v); } }; }} class abstract_printer { public: void print(std::ostream& os, const std::vector<int>& v) const { do_print(os, v); } virtual ~abstract_printer() { std::cout << "~abstract_printer()" << std::endl; } protected: virtual void do_print(std::ostream& os, const std::vector<int>& elements) const = 0; }; class separator_printer : public abstract_printer { public: explicit separator_printer(const std::string& sep) : separator(sep) {} protected: virtual void do_print(std::ostream& os, const std::vector<int>& v) const { for(int i : v){ os << separator.c_str() << i; } } private: std::string separator; }; class column_separator_printer : public abstract_printer { public: column_separator_printer(const std::string& sep, std::size_t num_columns) : separator(sep), cols(num_columns) {} protected: virtual void do_print(std::ostream& os, const std::vector<int>& v) const { std::size_t count = 0; for(int i : v){ os << i; int temp = i; ++temp; os << separator.c_str(); if(++count % cols == 0) { os << "\n"; } } } private: std::string separator; std::size_t cols; }; void print() { int test[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; std::vector<int> vtest(test, test + 10); typedef any<mpl::vector<printable<>, copy_constructible<>>> polyprintable; std::vector<polyprintable> printers; printers.push_back(polyprintable(separator_printer(","))); printers.push_back(polyprintable(column_separator_printer(",", 4))); for(polyprintable& printer : printers) { printer.print(std::cout, vtest); std::cout << std::endl; } } int main() { print(); } -----------------------------------