Boost logo

Boost :

Subject: Re: [boost] Formal Review Request: TypeErasure
From: Thomas Petit (thomas.petit33_at_[hidden])
Date: 2012-05-30 09:06:30


2012/5/30 Steven Watanabe <watanabesj_at_[hidden]>

>
> 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();
}

-----------------------------------


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk