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 const void* get_value(void* const * src) = 0;
48     virtual ::size_t get_size() = 0;
49     virtual const std::type_info& type() = 0;
50     virtual void print(std::ostream& out, void* const* src) = 0;
51 };
52 
53 template<typename T>
54 struct typed_base_any_policy : base_any_policy
55 {
get_sizetyped_base_any_policy56     virtual ::size_t get_size() { return sizeof(T); }
typetyped_base_any_policy57     virtual const std::type_info& type() { return typeid(T); }
58 
59 };
60 
61 template<typename T>
62 struct small_any_policy : typed_base_any_policy<T>
63 {
static_deletesmall_any_policy64     virtual void static_delete(void**) { }
copy_from_valuesmall_any_policy65     virtual void copy_from_value(void const* src, void** dest)
66     {
67         new (dest) T(* reinterpret_cast<T const*>(src));
68     }
clonesmall_any_policy69     virtual void clone(void* const* src, void** dest) { *dest = *src; }
movesmall_any_policy70     virtual void move(void* const* src, void** dest) { *dest = *src; }
get_valuesmall_any_policy71     virtual void* get_value(void** src) { return reinterpret_cast<void*>(src); }
get_valuesmall_any_policy72     virtual const void* get_value(void* const * src) { return reinterpret_cast<const void*>(src); }
printsmall_any_policy73     virtual void print(std::ostream& out, void* const* src) { out << *reinterpret_cast<T const*>(src); }
74 };
75 
76 template<typename T>
77 struct big_any_policy : typed_base_any_policy<T>
78 {
static_deletebig_any_policy79     virtual void static_delete(void** x)
80     {
81         if (* x) {
82           delete (* reinterpret_cast<T**>(x)); *x = NULL;
83         }
84     }
copy_from_valuebig_any_policy85     virtual void copy_from_value(void const* src, void** dest)
86     {
87         *dest = new T(*reinterpret_cast<T const*>(src));
88     }
clonebig_any_policy89     virtual void clone(void* const* src, void** dest)
90     {
91         *dest = new T(**reinterpret_cast<T* const*>(src));
92     }
movebig_any_policy93     virtual void move(void* const* src, void** dest)
94     {
95         (*reinterpret_cast<T**>(dest))->~T();
96         **reinterpret_cast<T**>(dest) = **reinterpret_cast<T* const*>(src);
97     }
get_valuebig_any_policy98     virtual void* get_value(void** src) { return *src; }
get_valuebig_any_policy99     virtual const void* get_value(void* const * src) { return *src; }
printbig_any_policy100     virtual void print(std::ostream& out, void* const* src) { out << *reinterpret_cast<T const*>(*src); }
101 };
102 
103 template<typename T>
104 struct choose_policy
105 {
106     typedef big_any_policy<T> type;
107 };
108 
109 template<typename T>
110 struct choose_policy<T*>
111 {
112     typedef small_any_policy<T*> type;
113 };
114 
115 struct any;
116 
117 /// Choosing the policy for an any type is illegal, but should never happen.
118 /// This is designed to throw a compiler error.
119 template<>
120 struct choose_policy<any>
121 {
122     typedef void type;
123 };
124 
125 /// Specializations for small types.
126 #define SMALL_POLICY(TYPE) \
127     template<> \
128     struct choose_policy<TYPE> { typedef small_any_policy<TYPE> type; \
129     }
130 
131 SMALL_POLICY(signed char);
132 SMALL_POLICY(unsigned char);
133 SMALL_POLICY(signed short);
134 SMALL_POLICY(unsigned short);
135 SMALL_POLICY(signed int);
136 SMALL_POLICY(unsigned int);
137 SMALL_POLICY(signed long);
138 SMALL_POLICY(unsigned long);
139 SMALL_POLICY(float);
140 SMALL_POLICY(bool);
141 
142 //#undef SMALL_POLICY
143 
144 /// This function will return a different policy for each type.
145 template<typename T>
146 base_any_policy* get_policy()
147 {
148     static typename choose_policy<T>::type policy;
149     return &policy;
150 }
151 } // namespace anyimpl
152 
153 class any
154 {
155 	typedef any any_t; // workaround for the NVCC compiler under windows
156 private:
157     // fields
158     anyimpl::base_any_policy* policy;
159     void* object;
160 
161 public:
162     /// Initializing constructor.
163     template <typename T>
164     any(const T& x)
165         : policy(anyimpl::get_policy<anyimpl::empty_any>()), object(NULL)
166     {
167         assign(x);
168     }
169 
170     /// Empty constructor.
171     any()
172         : policy(anyimpl::get_policy<anyimpl::empty_any>()), object(NULL)
173     { }
174 
175     /// Special initializing constructor for string literals.
176     any(const char* x)
177         : policy(anyimpl::get_policy<anyimpl::empty_any>()), object(NULL)
178     {
179         assign(x);
180     }
181 
182     /// Copy constructor.
183     any(const any& x)
184         : policy(anyimpl::get_policy<anyimpl::empty_any>()), object(NULL)
185     {
186         assign(x);
187     }
188 
189     /// Destructor.
190     ~any()
191     {
192         policy->static_delete(&object);
193     }
194 
195     /// Assignment function from another any.
196     any& assign(const any& x)
197     {
198         reset();
199         policy = x.policy;
200         policy->clone(&x.object, &object);
201         return *this;
202     }
203 
204     /// Assignment function.
205     template <typename T>
206     any_t& assign(const T& x)
207     {
208         reset();
209         policy = anyimpl::get_policy<T>();
210         policy->copy_from_value(&x, &object);
211         return *this;
212     }
213 
214     /// Assignment operator.
215     template<typename T>
216     any_t& operator=(const T& x)
217     {
218         return assign(x);
219     }
220 
221     /// Assignment operator, specialed for literal strings.
222     /// They have types like const char [6] which don't work as expected.
223     any& operator=(const char* x)
224     {
225         return assign(x);
226     }
227 
228     /// Utility functions
229     any& swap(any& x)
230     {
231         std::swap(policy, x.policy);
232         std::swap(object, x.object);
233         return *this;
234     }
235 
236     /// Cast operator. You can only cast to the original type.
237     template<typename T>
238     T& cast()
239     {
240         if (policy->type() != typeid(T)) throw anyimpl::bad_any_cast();
241         T* r = reinterpret_cast<T*>(policy->get_value(&object));
242         return *r;
243     }
244 
245     /// Cast operator. You can only cast to the original type.
246     template<typename T>
247     const T& cast() const
248     {
249         if (policy->type() != typeid(T)) throw anyimpl::bad_any_cast();
250         const T* r = reinterpret_cast<const T*>(policy->get_value(&object));
251         return *r;
252     }
253 
254     /// Returns true if the any contains no value.
255     bool empty() const
256     {
257         return policy->type() == typeid(anyimpl::empty_any);
258     }
259 
260     /// Frees any allocated memory, and sets the value to NULL.
261     void reset()
262     {
263         policy->static_delete(&object);
264         policy = anyimpl::get_policy<anyimpl::empty_any>();
265     }
266 
267     /// Returns true if the two types are the same.
268     bool compatible(const any& x) const
269     {
270         return policy->type() == x.policy->type();
271     }
272 
273     /// Returns if the type is compatible with the policy
274     template<typename T>
275     bool has_type()
276     {
277         return policy->type() == typeid(T);
278     }
279 
280     const std::type_info& type() const
281     {
282         return policy->type();
283     }
284 
285     friend std::ostream& operator <<(std::ostream& out, const any& any_val);
286 };
287 
288 inline std::ostream& operator <<(std::ostream& out, const any& any_val)
289 {
290     any_val.policy->print(out,&any_val.object);
291     return out;
292 }
293 
294 }
295 
296 #endif // FLANN_ANY_H_
297