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