Ne.app NeANT
The Ne.app NeANT User module of the NeANT distribution.
dynatype.cpp
Go to the documentation of this file.
1
29#include <iostream>
30#include <map>
31#include <typeinfo>
32
33#include <examples.h>
34
35
36// ordinary class whose objects are dynamically typed at runtime
38{
39 // member template class that encapsulates a per-specialization copy
40 // of an associative container (map) used to bind a specific instance
41 // of dynatype to its value
42 template <class T>
43 struct map {
44 typedef std::map<const dynatype*, T> map_type;
45
46 static map_type& get ();
47 };
48
49 // helper: removes this instance of dynatype from map
50 template <class T>
51 void remove () {
52 map<T>::get ().erase (this);
53 }
54
55 // helper: copies one instance of dynatype to another
56 template <class T>
57 void copy (const dynatype &rhs) {
58 // cast to <const T&> instead of <T> to avoid error on gcc 3.4.4/cygwin:
59 // error: invalid static_cast from type `const dynatype' to type `int'
60 *this = static_cast<const T&>(rhs);
61 }
62
63 // pointers to the helpers (do not depend on a template parameter)
64 void (dynatype::*p_remove)();
65 void (dynatype::*p_copy)(const dynatype&);
66
67 // provides access to the mapped data value or throws bad_cast
68 template <class T>
69 T& retrieve (const T*) {
70 if (map<T>::get ().end () == map<T>::get ().find (this))
71 throw std::bad_cast ();
72 return map<T>::get () [this];
73 }
74
75 // overload throws away const on template parameter
76 template <class T>
77 T& retrieve (const T*) const {
78 return const_cast<dynatype*>(this)->retrieve ((T*)0);
79 }
80
81public:
82
83 dynatype ();
84
85 // construct a dynatype object from a value of any type
86 template <class T>
87 dynatype (const T&);
88
89 // copy one dynatype object to another
91 : p_remove (rhs.p_remove),
92 p_copy (rhs.p_copy) {
93 (this->*p_copy)(rhs);
94 }
95
96 // assign one dynatype object to another
98
99 // remove `this' from the map destroy the object
101 (this->*p_remove)();
102 }
103
104 // retrieve a reference to the concrete type from an instance of
105 // dynatype throws std::bad_cast if the types don't match exactly
106 template <class T>
107 operator T& () {
108 return retrieve ((T*)0);
109 }
110
111 // retrieve a const reference to the concrete type from an instance of
112 // dynatype throws std::bad_cast if the types don't match exactly
113 template <class T>
114 operator const T& () const {
115 return retrieve ((T*)0);
116 }
117
118 // assign a value of any type to an instance of dynatype
119 template <class T>
120 dynatype& operator= (const T &t);
121};
122
123
124// 14.7.3, p6 - explicit specializations must be defined before first use
125template <>
126void dynatype::
127remove<void> ()
128{ /* no-op */ }
129
130
131template <>
132void dynatype::
133copy<void> (const dynatype&)
134{ /* no-op */ }
135
136
137// initialize with pointers to no-ops
139dynatype ()
140 : p_remove (&dynatype::remove<void>),
141 p_copy (&dynatype::copy<void>)
142{
143}
144
145
146template <class T>
147typename dynatype::map<T>::map_type&
148dynatype::map<T>::
149get ()
150{
151 static map_type m;
152
153 return m;
154}
155
156
157// construct a dynatype object from a value of any type
158template <class T>
160dynatype (const T &t)
161 : p_remove (&dynatype::remove<T>),
162 p_copy (&dynatype::copy<T>)
163{
164 *this = t;
165}
166
167
168// assign one dynatype object to another
170operator= (const dynatype &rhs)
171{
172 if (this != &rhs) {
173 // remove `this' from the associated map
174 (this->*p_remove)();
175
176 // copy pointers to helpers from the right-hand-side
177 p_remove = rhs.p_remove;
178 p_copy = rhs.p_copy;
179
180 // copy value of unknown type from rhs to `*this'
181 (this->*p_copy)(rhs);
182 }
183 return *this;
184}
185
186
187// assign a value of any type to an instance of dynatype
188template <class T>
190operator= (const T &t)
191{
192 // remove `this' from the map of the corresponding type
193 (this->*p_remove)();
194
195 // insert `t' into the map specialized on `T'
196 map<T>::get () [this] = t;
197
198 // assign pointers to the helpers
199 p_remove = &dynatype::remove<T>;
200 p_copy = &dynatype::copy<T>;
201
202 return *this;
203}
204
205
206int main ()
207{
208 try {
209
210 // create an instance of dynatype an initialized it with an int
211 dynatype v1 = 1;
212
213 std::cout << "static_cast<const int&>(v1 = 1) = ";
214 std::cout << static_cast<const int&>(v1) << '\n';
215
216 // assign a double to an instance of dynatype
217 v1 = 3.14;
218
219 std::cout << "static_cast<const double&>(v1 = 3.14) = ";
220 std::cout << static_cast<const double&>(v1) << '\n';
221
222 // copy construct an instance of dynatype
223 dynatype v2 = v1;
224
225 std::cout << "static_cast<const double&>(v2 = v1) = ";
226 std::cout << static_cast<const double&>(v2) << '\n';
227
228 // assign a const char* literal to an instance of dynatype
229 const char* const literal = "abc";
230 v2 = literal;
231
232 std::cout << "static_cast<const char* const&>(v2 = \"abc\") = ";
233 std::cout << static_cast<const char* const&>(v2) << '\n';
234
235 // assign one instance of dynatype to another
236 v1 = v2;
237
238 std::cout << "static_cast<const char* const&>(v1 = v2) = ";
239 std::cout << static_cast<const char* const&>(v1) << '\n';
240
241 // create uninitialized (untyped) instances of dynatype
242 dynatype v3, v4;
243
244 // assign one uninitialized instance to another
245 v3 = v4;
246
247 // attempt to extract any value from an unitialized dynatype fails
248 std::cout << "static_cast<const char&>(v3) = ";
249 std::cout << static_cast<const char&>(v3) << '\n';
250
251 }
252 catch (...) {
253 std::cerr << "exception\n";
254 }
255
256 return 0;
257}
#define m
Definition 17.names.cpp:129
#define T
Definition 17.names.cpp:163
#define rhs
Definition 17.names.cpp:536
#define t
Definition 17.names.cpp:136
#define v2
Definition 17.names.cpp:271
#define v1
Definition 17.names.cpp:245
const int end
dynatype(const dynatype &rhs)
Definition dynatype.cpp:90
dynatype & operator=(const dynatype &rhs)
Definition dynatype.cpp:170
int main()
Definition dynatype.cpp:206