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