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