#ifndef HolderH #define HolderH /*--------------------------------------------------------------------------- Holder.hpp --------------------------------------------------------------------------- Copyright (C) 2009/01 - 2009 Nowake nowake@fircewinds.net ----------------------------------------------------------------------------*/ #include "Multimethod.hpp" /////////////////////////////////////////////////////////////////////////// // Original any for fast multi method /////////////////////////////////////////////////////////////////////////// class Holder { public: Holder() : caddy_(0) {}; template Holder(const type_t& value) : caddy_(new Container(value)) {}; Holder(const Holder& other) : caddy_(other.caddy_ ? other.caddy_->clone() : 0) {}; ~Holder() { delete caddy_; }; Holder& swap(Holder& other) { std::swap(caddy_, other.caddy_); return *this; }; template Holder& operator=(const type_t& other) { Holder(other).swap(*this); return *this; }; Holder& operator=(const Holder& other) { Holder(other).swap(*this); return *this; }; bool empty() const { return !caddy_; }; const std::type_info& type() const { return caddy_ ? caddy_->type() : typeid(void); }; template type_t* cast() { return caddy_ && type() == typeid(type_t) ? &static_cast *>(caddy_)->content_ : 0; }; void reset() { Holder().swap(*this); }; template void reset() { Holder(new Container()).swap(*this); }; template void reset(arg1_t arg1) { Holder(new Container(arg1)).swap(*this); }; template void reset(arg1_t arg1, arg2_t arg2) { Holder(new Container(arg1, arg2)).swap(*this); }; template void reset(arg1_t arg1, arg2_t arg2, arg3_t arg3) { Holder(new Container(arg1, arg2, arg3)).swap(*this); }; unsigned int id() { return caddy_ ? caddy_->id() : id(); }; template static unsigned int id() { static unsigned int r(count()); return r; }; private: static unsigned int count() { static unsigned int r(0); return ++r; }; class Caddy { public: virtual ~Caddy() {}; virtual const std::type_info& type() const = 0; virtual Caddy* clone() const = 0; virtual unsigned int id() = 0; }; template class Container : public Caddy { public: Container() : content_() {}; Container(const type_t& value) : content_(value) {}; template Container(arg1_t& value1) : content_(value1) {}; template Container(arg1_t& value1, arg2_t& value2) : content_(value1, value2) {}; template Container(arg1_t& value1, arg2_t& value2, arg3_t& value3) : content_(value1, value2, value3) {}; virtual const std::type_info& type() const { return typeid(type_t); }; virtual Container* clone() const { return new Container(content_); }; virtual unsigned int id() { return Holder::id(); }; type_t content_; }; Caddy* caddy_; template Holder(Container* value) : caddy_(value) {}; public: // Method entry template static bool entry() { return Multimethod::entry(); }; template static bool entry() { return Multimethod::entry(); }; template static bool entry() { return Multimethod::entry(); }; template static bool entry() { return Multimethod::entry(); }; public: // Multi Method Holder operator()() { return Multimethod::apply(*this); }; template Holder operator()(T0& arg1) { return Multimethod::apply(*this, arg1); }; template Holder operator()(const T0& arg1) { return Multimethod::apply(*this, arg1); }; template Holder operator()(T0& arg1, T1& arg2) { return Multimethod::apply(*this, arg1, arg2); }; template Holder operator()(const T0& arg1, T1& arg2) { return Multimethod::apply(*this, arg1, arg2); }; template Holder operator()(T0& arg1, const T1& arg2) { return Multimethod::apply(*this, arg1, arg2); }; template Holder operator()(const T0& arg1, const T1& arg2) { return Multimethod::apply(*this, arg1, arg2); }; template Holder operator()(T0& arg1, T1& arg2, T2& arg3) { return Multimethod::apply(*this, arg1, arg2, arg3); }; template Holder operator()(const T0& arg1, T1& arg2, T2& arg3) { return Multimethod::apply(*this, arg1, arg2, arg3); }; template Holder operator()(T0& arg1, const T1& arg2, T2& arg3) { return Multimethod::apply(*this, arg1, arg2, arg3); }; template Holder operator()(T0& arg1, T1& arg2, const T2& arg3) { return Multimethod::apply(*this, arg1, arg2, arg3); }; template Holder operator()(const T0& arg1, const T1& arg2, T2& arg3) { return Multimethod::apply(*this, arg1, arg2, arg3); }; template Holder operator()(const T0& arg1, T1& arg2, const T2& arg3) { return Multimethod::apply(*this, arg1, arg2, arg3); }; template Holder operator()(T0& arg1, const T1& arg2, const T2& arg3) { return Multimethod::apply(*this, arg1, arg2, arg3); }; template Holder operator()(const T0& arg1, const T1& arg2, const T2& arg3) { return Multimethod::apply(*this, arg1, arg2, arg3); }; template Holder& operator()(); template<> Holder& operator()<0>() { operator()(); return *this; }; template Holder& operator()(Holder& arg1); template<> Holder& operator()<0>(Holder& arg1) { operator()(arg1); return *this; }; template<> Holder& operator()<1>(Holder& arg1) { operator()(arg1); return arg1; }; template Holder& operator()(Holder& arg1, Holder& arg2); template<> Holder& operator()<0>(Holder& arg1, Holder& arg2) { operator()(arg1, arg2); return *this; }; template<> Holder& operator()<1>(Holder& arg1, Holder& arg2) { operator()(arg1, arg2); return arg1; }; template<> Holder& operator()<2>(Holder& arg1, Holder& arg2) { operator()(arg1, arg2); return arg2; }; template Holder& operator()(Holder& arg1, Holder& arg2, Holder& arg3); template<> Holder& operator()<0>(Holder& arg1, Holder& arg2, Holder& arg3) { operator()(arg1, arg2, arg3); return *this; }; template<> Holder& operator()<1>(Holder& arg1, Holder& arg2, Holder& arg3) { operator()(arg1, arg2, arg3); return arg1; }; template<> Holder& operator()<2>(Holder& arg1, Holder& arg2, Holder& arg3) { operator()(arg1, arg2, arg3); return arg2; }; template<> Holder& operator()<3>(Holder& arg1, Holder& arg2, Holder& arg3) { operator()(arg1, arg2, arg3); return arg3; }; }; class holder_bad_cast : public std::bad_cast { public: virtual const char * what() const throw() { return "bad_cast: failed conversion using holder_cast"; }; }; template type_t* holder_cast(Holder* operand) { return operand->cast(); }; template inline const type_t* holder_cast(const Holder * operand) { return holder_cast(const_cast(operand)); }; template type_t holder_cast(Holder& operand) { typedef typename remove_reference::type nonref; nonref* result = holder_cast(&operand); if(!result) boost::throw_exception(holder_bad_cast()); return *result; }; template inline type_t holder_cast(const Holder& operand) { return holder_cast::type&>(const_cast(operand)); }; template<> struct Multimethod::Traits { typedef unsigned int index_type; static unsigned int id(Holder& target) { return target.id(); }; template static unsigned int id() { return Holder::id(); }; template static type_t cast(Holder& operand) { return holder_cast::type&>(operand); }; }; #endif