Ticket #2749: Holder.hpp

File Holder.hpp, 9.4 KB (added by anonymous, 14 years ago)

Customized boost::any to fit multi method

Line 
1#ifndef HolderH
2#define HolderH
3/*---------------------------------------------------------------------------
4 Holder.hpp
5
6 ---------------------------------------------------------------------------
7 Copyright (C) 2009/01 - 2009 Nowake nowake@fircewinds.net
8----------------------------------------------------------------------------*/
9
10#include "Multimethod.hpp"
11
12 ///////////////////////////////////////////////////////////////////////////
13 // Original any for fast multi method
14 ///////////////////////////////////////////////////////////////////////////
15 class Holder {
16 public:
17 Holder() : caddy_(0) {};
18 template<typename type_t> Holder(const type_t& value) : caddy_(new Container<type_t>(value)) {};
19 Holder(const Holder& other) : caddy_(other.caddy_ ? other.caddy_->clone() : 0) {};
20 ~Holder() { delete caddy_; };
21 Holder& swap(Holder& other) {
22 std::swap(caddy_, other.caddy_);
23 return *this;
24 };
25 template<typename type_t>
26 Holder& operator=(const type_t& other) {
27 Holder(other).swap(*this);
28 return *this;
29 };
30 Holder& operator=(const Holder& other) {
31 Holder(other).swap(*this);
32 return *this;
33 };
34 bool empty() const { return !caddy_; };
35 const std::type_info& type() const { return caddy_ ? caddy_->type() : typeid(void); };
36 template<typename type_t>
37 type_t* cast() {
38 return caddy_ && type() == typeid(type_t) ? &static_cast<Container<type_t> *>(caddy_)->content_ : 0;
39 };
40 void reset() { Holder().swap(*this); };
41 template<typename type_t>
42 void reset() { Holder(new Container<type_t>()).swap(*this); };
43 template<typename type_t, typename arg1_t>
44 void reset(arg1_t arg1) { Holder(new Container<type_t>(arg1)).swap(*this); };
45 template<typename type_t, typename arg1_t, typename arg2_t>
46 void reset(arg1_t arg1, arg2_t arg2) { Holder(new Container<type_t>(arg1, arg2)).swap(*this); };
47 template<typename type_t, typename arg1_t, typename arg2_t, typename arg3_t>
48 void reset(arg1_t arg1, arg2_t arg2, arg3_t arg3) { Holder(new Container<type_t>(arg1, arg2, arg3)).swap(*this); };
49 unsigned int id() { return caddy_ ? caddy_->id() : id<void>(); };
50 template<typename type_t>
51 static unsigned int id() { static unsigned int r(count()); return r; };
52 private:
53 static unsigned int count() { static unsigned int r(0); return ++r; };
54 class Caddy {
55 public:
56 virtual ~Caddy() {};
57 virtual const std::type_info& type() const = 0;
58 virtual Caddy* clone() const = 0;
59 virtual unsigned int id() = 0;
60 };
61 template<typename type_t>
62 class Container : public Caddy {
63 public:
64 Container() : content_() {};
65 Container(const type_t& value) : content_(value) {};
66 template<typename arg1_t>
67 Container(arg1_t& value1) : content_(value1) {};
68 template<typename arg1_t, typename arg2_t>
69 Container(arg1_t& value1, arg2_t& value2) : content_(value1, value2) {};
70 template<typename arg1_t, typename arg2_t, typename arg3_t>
71 Container(arg1_t& value1, arg2_t& value2, arg3_t& value3) : content_(value1, value2, value3) {};
72 virtual const std::type_info& type() const { return typeid(type_t); };
73 virtual Container* clone() const { return new Container(content_); };
74 virtual unsigned int id() { return Holder::id<type_t>(); };
75 type_t content_;
76 };
77 Caddy* caddy_;
78 template<typename T>
79 Holder(Container<T>* value) : caddy_(value) {};
80 public: // Method entry
81 template<typename M0>
82 static bool entry() { return Multimethod::entry<Holder, Holder, M0>(); };
83 template<typename M0, typename A1>
84 static bool entry() { return Multimethod::entry<Holder, Holder, M0, A1>(); };
85 template<typename M0, typename A1, typename A2>
86 static bool entry() { return Multimethod::entry<Holder, Holder, M0, A1, A2>(); };
87 template<typename M0, typename A1, typename A2, typename A3>
88 static bool entry() { return Multimethod::entry<Holder, Holder, M0, A1, A2, A3>(); };
89 public: // Multi Method
90 Holder operator()() { return Multimethod::apply<Holder, Holder>(*this); };
91 template <typename T0>
92 Holder operator()(T0& arg1) { return Multimethod::apply<Holder, Holder>(*this, arg1); };
93 template <typename T0>
94 Holder operator()(const T0& arg1) { return Multimethod::apply<Holder, Holder>(*this, arg1); };
95 template <typename T0, typename T1>
96 Holder operator()(T0& arg1, T1& arg2) { return Multimethod::apply<Holder, Holder>(*this, arg1, arg2); };
97 template <typename T0, typename T1>
98 Holder operator()(const T0& arg1, T1& arg2) { return Multimethod::apply<Holder, Holder>(*this, arg1, arg2); };
99 template <typename T0, typename T1>
100 Holder operator()(T0& arg1, const T1& arg2) { return Multimethod::apply<Holder, Holder>(*this, arg1, arg2); };
101 template <typename T0, typename T1>
102 Holder operator()(const T0& arg1, const T1& arg2) { return Multimethod::apply<Holder, Holder>(*this, arg1, arg2); };
103 template <typename T0, typename T1, typename T2>
104 Holder operator()(T0& arg1, T1& arg2, T2& arg3) { return Multimethod::apply<Holder, Holder>(*this, arg1, arg2, arg3); };
105 template <typename T0, typename T1, typename T2>
106 Holder operator()(const T0& arg1, T1& arg2, T2& arg3) { return Multimethod::apply<Holder, Holder>(*this, arg1, arg2, arg3); };
107 template <typename T0, typename T1, typename T2>
108 Holder operator()(T0& arg1, const T1& arg2, T2& arg3) { return Multimethod::apply<Holder, Holder>(*this, arg1, arg2, arg3); };
109 template <typename T0, typename T1, typename T2>
110 Holder operator()(T0& arg1, T1& arg2, const T2& arg3) { return Multimethod::apply<Holder, Holder>(*this, arg1, arg2, arg3); };
111 template <typename T0, typename T1, typename T2>
112 Holder operator()(const T0& arg1, const T1& arg2, T2& arg3) { return Multimethod::apply<Holder, Holder>(*this, arg1, arg2, arg3); };
113 template <typename T0, typename T1, typename T2>
114 Holder operator()(const T0& arg1, T1& arg2, const T2& arg3) { return Multimethod::apply<Holder, Holder>(*this, arg1, arg2, arg3); };
115 template <typename T0, typename T1, typename T2>
116 Holder operator()(T0& arg1, const T1& arg2, const T2& arg3) { return Multimethod::apply<Holder, Holder>(*this, arg1, arg2, arg3); };
117 template <typename T0, typename T1, typename T2>
118 Holder operator()(const T0& arg1, const T1& arg2, const T2& arg3) { return Multimethod::apply<Holder, Holder>(*this, arg1, arg2, arg3); };
119 template<unsigned int> Holder& operator()();
120 template<> Holder& operator()<0>() { operator()(); return *this; };
121 template<unsigned int> Holder& operator()(Holder& arg1);
122 template<> Holder& operator()<0>(Holder& arg1) { operator()(arg1); return *this; };
123 template<> Holder& operator()<1>(Holder& arg1) { operator()(arg1); return arg1; };
124 template<unsigned int> Holder& operator()(Holder& arg1, Holder& arg2);
125 template<> Holder& operator()<0>(Holder& arg1, Holder& arg2) { operator()(arg1, arg2); return *this; };
126 template<> Holder& operator()<1>(Holder& arg1, Holder& arg2) { operator()(arg1, arg2); return arg1; };
127 template<> Holder& operator()<2>(Holder& arg1, Holder& arg2) { operator()(arg1, arg2); return arg2; };
128 template<unsigned int> Holder& operator()(Holder& arg1, Holder& arg2, Holder& arg3);
129 template<> Holder& operator()<0>(Holder& arg1, Holder& arg2, Holder& arg3) { operator()(arg1, arg2, arg3); return *this; };
130 template<> Holder& operator()<1>(Holder& arg1, Holder& arg2, Holder& arg3) { operator()(arg1, arg2, arg3); return arg1; };
131 template<> Holder& operator()<2>(Holder& arg1, Holder& arg2, Holder& arg3) { operator()(arg1, arg2, arg3); return arg2; };
132 template<> Holder& operator()<3>(Holder& arg1, Holder& arg2, Holder& arg3) { operator()(arg1, arg2, arg3); return arg3; };
133 };
134
135 class holder_bad_cast : public std::bad_cast {
136 public:
137 virtual const char * what() const throw() { return "bad_cast: failed conversion using holder_cast"; };
138 };
139
140 template<typename type_t>
141 type_t* holder_cast(Holder* operand) { return operand->cast<type_t>(); };
142
143 template<typename type_t>
144 inline const type_t* holder_cast(const Holder * operand) {
145 return holder_cast<type_t>(const_cast<Holder *>(operand));
146 };
147
148 template<typename type_t>
149 type_t holder_cast(Holder& operand) {
150 typedef typename remove_reference<type_t>::type nonref;
151 nonref* result = holder_cast<nonref>(&operand);
152 if(!result)
153 boost::throw_exception(holder_bad_cast());
154 return *result;
155 };
156
157 template<typename type_t>
158 inline type_t holder_cast(const Holder& operand) {
159 return holder_cast<const remove_reference<type_t>::type&>(const_cast<Holder&>(operand));
160 };
161
162 template<> struct Multimethod::Traits<Holder> {
163 typedef unsigned int index_type;
164 static unsigned int id(Holder& target) { return target.id(); };
165 template<typename target_t>
166 static unsigned int id() { return Holder::id<target_t>(); };
167 template<typename type_t>
168 static type_t cast(Holder& operand) { return holder_cast<remove_reference<type_t>::type&>(operand); };
169 };
170
171
172#endif