#include <boost/mpl/begin_end.hpp>

#include <iostream>

namespace mpl = boost::mpl;

namespace aux {
	template <class Begin_, class End_>
	struct DumpImpl {
		typedef typename Begin_::type Type;
		static void dump(void* p, std::ostream& os =std::cout) {
			Type* t = (Type*) p;
			os << (size_t)t << ": " << *t << std::endl;
			if (sizeof(Type) < 4) p = ((void**)p) + 1;
			else p = (void*)(t+1);
			DumpImpl<typename Begin_::next, End_>::dump(p, os);
		}
	};
	template <class End_>
	struct DumpImpl<End_, End_> {
		static void dump(void*, std::ostream&) {}
	};
}

template <class Seq_, int derivs_ =2>
class Dumper {
public:
	static void dump(void* p, std::ostream& os =std::cout) {
#if __GNUC__ == 2
		typedef typename mpl::begin<Seq_>::type::type Type;
		std::cout << (size_t)p << ": " << *(Type*)p << std::endl;
		if (sizeof(Type)+derivs_ < 4) p = ((void**)p) + 1;
		else {
			p = ((Type*)p+1);
			if (derivs_) p = ((void**)p) + 1;
		}
		aux::DumpImpl <typename mpl::begin<Seq_>::type::next,
		               typename mpl::end<Seq_>::type>::dump(p, os);
#else
		aux::DumpImpl <typename mpl::begin<Seq_>::type,
		               typename mpl::end<Seq_>::type>::dump(p, os);
#endif
	}
	void dump(std::ostream& os =std::cout) {
	    void* ptr = (void*)this;
#if __GNUC__ == 2
		typedef typename mpl::begin<Seq_>::type::type Type;
		ptr = (void*)(((char*)ptr)-sizeof(Type*));
#endif
	    dump(ptr, os);
	}
};


