| | #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 |
| |
|