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