#ifndef OPENCV_FLANN_ANY_H_ #define OPENCV_FLANN_ANY_H_ /* * (C) Copyright Christopher Diggins 2005-2011 * (C) Copyright Pablo Aguilar 2005 * (C) Copyright Kevlin Henney 2001 * * Distributed under the Boost Software License, Version 1.0. (See * accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt * * Adapted for FLANN by Marius Muja */ #include "defines.h" #include #include #include namespace cvflann { namespace anyimpl { struct bad_any_cast { }; 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; virtual ~base_any_policy() {} }; template 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 struct small_any_policy : typed_base_any_policy { virtual void static_delete(void**) { } virtual void copy_from_value(void const* src, void** dest) { new (dest) T(* reinterpret_cast(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(src); } virtual const void* get_value(void* const * src) { return reinterpret_cast(src); } virtual void print(std::ostream& out, void* const* src) { out << *reinterpret_cast(src); } }; template struct big_any_policy : typed_base_any_policy { virtual void static_delete(void** x) { if (* x) delete (* reinterpret_cast(x)); *x = NULL; } virtual void copy_from_value(void const* src, void** dest) { *dest = new T(*reinterpret_cast(src)); } virtual void clone(void* const* src, void** dest) { *dest = new T(**reinterpret_cast(src)); } virtual void move(void* const* src, void** dest) { (*reinterpret_cast(dest))->~T(); **reinterpret_cast(dest) = **reinterpret_cast(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(*src); } }; template<> inline void big_any_policy::print(std::ostream& out, void* const* src) { out << int(*reinterpret_cast(*src)); } template<> inline void big_any_policy::print(std::ostream& out, void* const* src) { out << int(*reinterpret_cast(*src)); } template<> inline void big_any_policy::print(std::ostream& out, void* const* src) { out << (*reinterpret_cast(*src)).c_str(); } template struct choose_policy { typedef big_any_policy type; }; template struct choose_policy { typedef small_any_policy type; }; struct any; /// Choosing the policy for an any type is illegal, but should never happen. /// This is designed to throw a compiler error. template<> struct choose_policy { typedef void type; }; /// Specializations for small types. #define SMALL_POLICY(TYPE) \ template<> \ struct choose_policy { typedef small_any_policy 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); #undef SMALL_POLICY template class SinglePolicy { SinglePolicy(); SinglePolicy(const SinglePolicy& other); SinglePolicy& operator=(const SinglePolicy& other); public: static base_any_policy* get_policy(); private: static typename choose_policy::type policy; }; template typename choose_policy::type SinglePolicy::policy; /// This function will return a different policy for each type. template inline base_any_policy* SinglePolicy::get_policy() { return &policy; } } // namespace anyimpl struct any { private: // fields anyimpl::base_any_policy* policy; void* object; public: /// Initializing constructor. template any(const T& x) : policy(anyimpl::SinglePolicy::get_policy()), object(NULL) { assign(x); } /// Empty constructor. any() : policy(anyimpl::SinglePolicy::get_policy()), object(NULL) { } /// Special initializing constructor for string literals. any(const char* x) : policy(anyimpl::SinglePolicy::get_policy()), object(NULL) { assign(x); } /// Copy constructor. any(const any& x) : policy(anyimpl::SinglePolicy::get_policy()), object(NULL) { assign(x); } /// Destructor. ~any() { policy->static_delete(&object); } /// Assignment function from another any. any& assign(const any& x) { reset(); policy = x.policy; policy->clone(&x.object, &object); return *this; } /// Assignment function. template any& assign(const T& x) { reset(); policy = anyimpl::SinglePolicy::get_policy(); policy->copy_from_value(&x, &object); return *this; } /// Assignment operator. template any& operator=(const T& x) { return assign(x); } /// Assignment operator. Template-based version above doesn't work as expected. We need regular assignment operator here. any& operator=(const any& x) { return assign(x); } /// Assignment operator, specialed for literal strings. /// They have types like const char [6] which don't work as expected. any& operator=(const char* x) { return assign(x); } /// Utility functions any& swap(any& x) { std::swap(policy, x.policy); std::swap(object, x.object); return *this; } /// Cast operator. You can only cast to the original type. template T& cast() { if (policy->type() != typeid(T)) throw anyimpl::bad_any_cast(); T* r = reinterpret_cast(policy->get_value(&object)); return *r; } /// Cast operator. You can only cast to the original type. template const T& cast() const { if (policy->type() != typeid(T)) throw anyimpl::bad_any_cast(); const T* r = reinterpret_cast(policy->get_value(&object)); return *r; } /// Returns true if the any contains no value. bool empty() const { return policy->type() == typeid(anyimpl::empty_any); } /// Frees any allocated memory, and sets the value to NULL. void reset() { policy->static_delete(&object); policy = anyimpl::SinglePolicy::get_policy(); } /// Returns true if the two types are the same. bool compatible(const any& x) const { return policy->type() == x.policy->type(); } /// Returns if the type is compatible with the policy template 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 // OPENCV_FLANN_ANY_H_