| #ifndef FLANN_ANY_H_ |
| #define FLANN_ANY_H_ |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| #include <stdexcept> |
| #include <ostream> |
| #include <typeinfo> |
|
|
| namespace flann |
| { |
|
|
| namespace anyimpl |
| { |
|
|
| struct bad_any_cast : public std::runtime_error |
| { |
| bad_any_cast() : std::runtime_error("Cannot convert 'any' value") { } |
| }; |
|
|
| struct empty_any |
| { |
| }; |
|
|
| inline std::ostream& operator <<(std::ostream& out, const empty_any&) |
| { |
| out << "[empty_any]"; |
| return out; |
| } |
|
|
| struct base_any_policy |
| { |
| virtual void static_delete(void** x) = 0; |
| virtual void copy_from_value(void const* src, void** dest) = 0; |
| virtual void clone(void* const* src, void** dest) = 0; |
| virtual void move(void* const* src, void** dest) = 0; |
| virtual void* get_value(void** src) = 0; |
| virtual const void* get_value(void* const * src) = 0; |
| virtual ::size_t get_size() = 0; |
| virtual const std::type_info& type() = 0; |
| virtual void print(std::ostream& out, void* const* src) = 0; |
| }; |
|
|
| template<typename T> |
| struct typed_base_any_policy : base_any_policy |
| { |
| virtual ::size_t get_size() { return sizeof(T); } |
| virtual const std::type_info& type() { return typeid(T); } |
|
|
| }; |
|
|
| template<typename T> |
| struct small_any_policy : typed_base_any_policy<T> |
| { |
| virtual void static_delete(void**) { } |
| virtual void copy_from_value(void const* src, void** dest) |
| { |
| new (dest) T(* reinterpret_cast<T const*>(src)); |
| } |
| virtual void clone(void* const* src, void** dest) { *dest = *src; } |
| virtual void move(void* const* src, void** dest) { *dest = *src; } |
| virtual void* get_value(void** src) { return reinterpret_cast<void*>(src); } |
| virtual const void* get_value(void* const * src) { return reinterpret_cast<const void*>(src); } |
| virtual void print(std::ostream& out, void* const* src) { out << *reinterpret_cast<T const*>(src); } |
| }; |
|
|
| template<typename T> |
| struct big_any_policy : typed_base_any_policy<T> |
| { |
| virtual void static_delete(void** x) |
| { |
| if (* x) { |
| delete (* reinterpret_cast<T**>(x)); *x = NULL; |
| } |
| } |
| virtual void copy_from_value(void const* src, void** dest) |
| { |
| *dest = new T(*reinterpret_cast<T const*>(src)); |
| } |
| virtual void clone(void* const* src, void** dest) |
| { |
| *dest = new T(**reinterpret_cast<T* const*>(src)); |
| } |
| virtual void move(void* const* src, void** dest) |
| { |
| (*reinterpret_cast<T**>(dest))->~T(); |
| **reinterpret_cast<T**>(dest) = **reinterpret_cast<T* const*>(src); |
| } |
| virtual void* get_value(void** src) { return *src; } |
| virtual const void* get_value(void* const * src) { return *src; } |
| virtual void print(std::ostream& out, void* const* src) { out << *reinterpret_cast<T const*>(*src); } |
| }; |
|
|
| template<typename T> |
| struct choose_policy |
| { |
| typedef big_any_policy<T> type; |
| }; |
|
|
| template<typename T> |
| struct choose_policy<T*> |
| { |
| typedef small_any_policy<T*> type; |
| }; |
|
|
| struct any; |
|
|
| |
| |
| template<> |
| struct choose_policy<any> |
| { |
| typedef void type; |
| }; |
|
|
| |
| #define SMALL_POLICY(TYPE) \ |
| template<> \ |
| struct choose_policy<TYPE> { typedef small_any_policy<TYPE> type; \ |
| } |
|
|
| SMALL_POLICY(signed char); |
| SMALL_POLICY(unsigned char); |
| SMALL_POLICY(signed short); |
| SMALL_POLICY(unsigned short); |
| SMALL_POLICY(signed int); |
| SMALL_POLICY(unsigned int); |
| SMALL_POLICY(signed long); |
| SMALL_POLICY(unsigned long); |
| SMALL_POLICY(float); |
| SMALL_POLICY(bool); |
|
|
| |
|
|
| |
| template<typename T> |
| base_any_policy* get_policy() |
| { |
| static typename choose_policy<T>::type policy; |
| return &policy; |
| } |
| } |
|
|
| class any |
| { |
| typedef any any_t; |
| private: |
| |
| anyimpl::base_any_policy* policy; |
| void* object; |
|
|
| public: |
| |
| template <typename T> |
| any(const T& x) |
| : policy(anyimpl::get_policy<anyimpl::empty_any>()), object(NULL) |
| { |
| assign(x); |
| } |
|
|
| |
| any() |
| : policy(anyimpl::get_policy<anyimpl::empty_any>()), object(NULL) |
| { } |
|
|
| |
| any(const char* x) |
| : policy(anyimpl::get_policy<anyimpl::empty_any>()), object(NULL) |
| { |
| assign(x); |
| } |
|
|
| |
| any(const any& x) |
| : policy(anyimpl::get_policy<anyimpl::empty_any>()), object(NULL) |
| { |
| assign(x); |
| } |
|
|
| |
| ~any() |
| { |
| policy->static_delete(&object); |
| } |
|
|
| |
| any& assign(const any& x) |
| { |
| reset(); |
| policy = x.policy; |
| policy->clone(&x.object, &object); |
| return *this; |
| } |
|
|
| |
| template <typename T> |
| any_t& assign(const T& x) |
| { |
| reset(); |
| policy = anyimpl::get_policy<T>(); |
| policy->copy_from_value(&x, &object); |
| return *this; |
| } |
|
|
| |
| template<typename T> |
| any_t& operator=(const T& x) |
| { |
| return assign(x); |
| } |
|
|
| |
| |
| any& operator=(const char* x) |
| { |
| return assign(x); |
| } |
|
|
| |
| any& swap(any& x) |
| { |
| std::swap(policy, x.policy); |
| std::swap(object, x.object); |
| return *this; |
| } |
|
|
| |
| template<typename T> |
| T& cast() |
| { |
| if (policy->type() != typeid(T)) throw anyimpl::bad_any_cast(); |
| T* r = reinterpret_cast<T*>(policy->get_value(&object)); |
| return *r; |
| } |
|
|
| |
| template<typename T> |
| const T& cast() const |
| { |
| if (policy->type() != typeid(T)) throw anyimpl::bad_any_cast(); |
| const T* r = reinterpret_cast<const T*>(policy->get_value(&object)); |
| return *r; |
| } |
|
|
| |
| bool empty() const |
| { |
| return policy->type() == typeid(anyimpl::empty_any); |
| } |
|
|
| |
| void reset() |
| { |
| policy->static_delete(&object); |
| policy = anyimpl::get_policy<anyimpl::empty_any>(); |
| } |
|
|
| |
| bool compatible(const any& x) const |
| { |
| return policy->type() == x.policy->type(); |
| } |
|
|
| |
| template<typename T> |
| bool has_type() |
| { |
| return policy->type() == typeid(T); |
| } |
|
|
| const std::type_info& type() const |
| { |
| return policy->type(); |
| } |
|
|
| friend std::ostream& operator <<(std::ostream& out, const any& any_val); |
| }; |
|
|
| inline std::ostream& operator <<(std::ostream& out, const any& any_val) |
| { |
| any_val.policy->print(out,&any_val.object); |
| return out; |
| } |
|
|
| } |
|
|
| #endif |
|
|