1 #ifndef FLANN_ANY_H_
2 #define FLANN_ANY_H_
3 /*
4  * (C) Copyright Christopher Diggins 2005-2011
5  * (C) Copyright Pablo Aguilar 2005
6  * (C) Copyright Kevlin Henney 2001
7  *
8  * Distributed under the Boost Software License, Version 1.0. (See
9  * accompanying file LICENSE_1_0.txt or copy at
10  * http://www.boost.org/LICENSE_1_0.txt
11  *
12  * Adapted for FLANN by Marius Muja
13  */
14 
15 #include <stdexcept>
16 #include <ostream>
17 #include <typeinfo>
18 
19 namespace flann
20 {
21 
22 namespace anyimpl
23 {
24 
25 struct bad_any_cast : public std::runtime_error
26 {
bad_any_castbad_any_cast27 	bad_any_cast() : std::runtime_error("Cannot convert 'any' value") { }
28 };
29 
30 struct empty_any
31 {
32 };
33 
34 inline std::ostream& operator <<(std::ostream& out, const empty_any&)
35 {
36     out << "[empty_any]";
37     return out;
38 }
39 
40 struct base_any_policy
41 {
42     virtual void static_delete(void** x) = 0;
43     virtual void copy_from_value(void const* src, void** dest) = 0;
44     virtual void clone(void* const* src, void** dest) = 0;
45     virtual void move(void* const* src, void** dest) = 0;
46     virtual void* get_value(void** src) = 0;
47     virtual size_t get_size() = 0;
48     virtual const std::type_info& type() = 0;
49     virtual void print(std::ostream& out, void* const* src) = 0;
50 };
51 
52 template<typename T>
53 struct typed_base_any_policy : base_any_policy
54 {
get_sizetyped_base_any_policy55     virtual size_t get_size() { return sizeof(T); }
typetyped_base_any_policy56     virtual const std::type_info& type() { return typeid(T); }
57 
58 };
59 
60 template<typename T>
61 struct small_any_policy : typed_base_any_policy<T>
62 {
static_deletesmall_any_policy63     virtual void static_delete(void**) { }
copy_from_valuesmall_any_policy64     virtual void copy_from_value(void const* src, void** dest)
65     {
66         new (dest) T(* reinterpret_cast<T const*>(src));
67     }
clonesmall_any_policy68     virtual void clone(void* const* src, void** dest) { *dest = *src; }
movesmall_any_policy69     virtual void move(void* const* src, void** dest) { *dest = *src; }
get_valuesmall_any_policy70     virtual void* get_value(void** src) { return reinterpret_cast<void*>(src); }
printsmall_any_policy71     virtual void print(std::ostream& out, void* const* src) { out << *reinterpret_cast<T const*>(src); }
72 };
73 
74 template<typename T>
75 struct big_any_policy : typed_base_any_policy<T>
76 {
static_deletebig_any_policy77     virtual void static_delete(void** x)
78     {
79         if (* x) delete (* reinterpret_cast<T**>(x)); *x = NULL;
80     }
copy_from_valuebig_any_policy81     virtual void copy_from_value(void const* src, void** dest)
82     {
83         *dest = new T(*reinterpret_cast<T const*>(src));
84     }
clonebig_any_policy85     virtual void clone(void* const* src, void** dest)
86     {
87         *dest = new T(**reinterpret_cast<T* const*>(src));
88     }
movebig_any_policy89     virtual void move(void* const* src, void** dest)
90     {
91         (*reinterpret_cast<T**>(dest))->~T();
92         **reinterpret_cast<T**>(dest) = **reinterpret_cast<T* const*>(src);
93     }
get_valuebig_any_policy94     virtual void* get_value(void** src) { return *src; }
printbig_any_policy95     virtual void print(std::ostream& out, void* const* src) { out << *reinterpret_cast<T const*>(*src); }
96 };
97 
98 template<typename T>
99 struct choose_policy
100 {
101     typedef big_any_policy<T> type;
102 };
103 
104 template<typename T>
105 struct choose_policy<T*>
106 {
107     typedef small_any_policy<T*> type;
108 };
109 
110 struct any;
111 
112 /// Choosing the policy for an any type is illegal, but should never happen.
113 /// This is designed to throw a compiler error.
114 template<>
115 struct choose_policy<any>
116 {
117     typedef void type;
118 };
119 
120 /// Specializations for small types.
121 #define SMALL_POLICY(TYPE) \
122     template<> \
123     struct choose_policy<TYPE> { typedef small_any_policy<TYPE> type; \
124     }
125 
126 SMALL_POLICY(signed char);
127 SMALL_POLICY(unsigned char);
128 SMALL_POLICY(signed short);
129 SMALL_POLICY(unsigned short);
130 SMALL_POLICY(signed int);
131 SMALL_POLICY(unsigned int);
132 SMALL_POLICY(signed long);
133 SMALL_POLICY(unsigned long);
134 SMALL_POLICY(float);
135 SMALL_POLICY(bool);
136 
137 #undef SMALL_POLICY
138 
139 /// This function will return a different policy for each type.
140 template<typename T>
141 base_any_policy* get_policy()
142 {
143     static typename choose_policy<T>::type policy;
144     return &policy;
145 }
146 } // namespace anyimpl
147 
148 class any
149 {
150 	typedef any any_t; // workaround for the NVCC compiler under windows
151 private:
152     // fields
153     anyimpl::base_any_policy* policy;
154     void* object;
155 
156 public:
157     /// Initializing constructor.
158     template <typename T>
159     any(const T& x)
160         : policy(anyimpl::get_policy<anyimpl::empty_any>()), object(NULL)
161     {
162         assign(x);
163     }
164 
165     /// Empty constructor.
166     any()
167         : policy(anyimpl::get_policy<anyimpl::empty_any>()), object(NULL)
168     { }
169 
170     /// Special initializing constructor for string literals.
171     any(const char* x)
172         : policy(anyimpl::get_policy<anyimpl::empty_any>()), object(NULL)
173     {
174         assign(x);
175     }
176 
177     /// Copy constructor.
178     any(const any& x)
179         : policy(anyimpl::get_policy<anyimpl::empty_any>()), object(NULL)
180     {
181         assign(x);
182     }
183 
184     /// Destructor.
185     ~any()
186     {
187         policy->static_delete(&object);
188     }
189 
190     /// Assignment function from another any.
191     any& assign(const any& x)
192     {
193         reset();
194         policy = x.policy;
195         policy->clone(&x.object, &object);
196         return *this;
197     }
198 
199     /// Assignment function.
200     template <typename T>
201     any_t& assign(const T& x)
202     {
203         reset();
204         policy = anyimpl::get_policy<T>();
205         policy->copy_from_value(&x, &object);
206         return *this;
207     }
208 
209     /// Assignment operator.
210     template<typename T>
211     any_t& operator=(const T& x)
212     {
213         return assign(x);
214     }
215 
216     /// Assignment operator, specialed for literal strings.
217     /// They have types like const char [6] which don't work as expected.
218     any& operator=(const char* x)
219     {
220         return assign(x);
221     }
222 
223     /// Utility functions
224     any& swap(any& x)
225     {
226         std::swap(policy, x.policy);
227         std::swap(object, x.object);
228         return *this;
229     }
230 
231     /// Cast operator. You can only cast to the original type.
232     template<typename T>
233     T& cast()
234     {
235         if (policy->type() != typeid(T)) throw anyimpl::bad_any_cast();
236         T* r = reinterpret_cast<T*>(policy->get_value(&object));
237         return *r;
238     }
239 
240     /// Cast operator. You can only cast to the original type.
241     template<typename T>
242     const T& cast() const
243     {
244         if (policy->type() != typeid(T)) throw anyimpl::bad_any_cast();
245         void* obj = const_cast<void*>(object);
246         T* r = reinterpret_cast<T*>(policy->get_value(&obj));
247         return *r;
248     }
249 
250     /// Returns true if the any contains no value.
251     bool empty() const
252     {
253         return policy->type() == typeid(anyimpl::empty_any);
254     }
255 
256     /// Frees any allocated memory, and sets the value to NULL.
257     void reset()
258     {
259         policy->static_delete(&object);
260         policy = anyimpl::get_policy<anyimpl::empty_any>();
261     }
262 
263     /// Returns true if the two types are the same.
264     bool compatible(const any& x) const
265     {
266         return policy->type() == x.policy->type();
267     }
268 
269     /// Returns if the type is compatible with the policy
270     template<typename T>
271     bool has_type()
272     {
273         return policy->type() == typeid(T);
274     }
275 
276     const std::type_info& type() const
277     {
278         return policy->type();
279     }
280 
281     friend std::ostream& operator <<(std::ostream& out, const any& any_val);
282 };
283 
284 inline std::ostream& operator <<(std::ostream& out, const any& any_val)
285 {
286     any_val.policy->print(out,&any_val.object);
287     return out;
288 }
289 
290 }
291 
292 #endif // FLANN_ANY_H_
293