#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 */ //! @cond IGNORED #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() CV_OVERRIDE { return sizeof(T); } virtual const std::type_info &type() CV_OVERRIDE { return typeid(T); } }; template struct small_any_policy CV_FINAL : typed_base_any_policy { virtual void static_delete(void **) CV_OVERRIDE {} virtual void copy_from_value(void const *src, void **dest) CV_OVERRIDE { new(dest) T(*reinterpret_cast(src)); } virtual void clone(void *const *src, void **dest) CV_OVERRIDE { *dest = *src; } virtual void move(void *const *src, void **dest) CV_OVERRIDE { *dest = *src; } virtual void * get_value(void **src) CV_OVERRIDE { return reinterpret_cast(src); } virtual const void * get_value(void *const *src) CV_OVERRIDE { return reinterpret_cast(src); } virtual void print(std::ostream &out, void *const *src) CV_OVERRIDE { out << *reinterpret_cast(src); } }; template struct big_any_policy CV_FINAL : typed_base_any_policy { virtual void static_delete(void **x) CV_OVERRIDE { if (*x) delete (*reinterpret_cast(x)); *x = NULL; } virtual void copy_from_value(void const *src, void **dest) CV_OVERRIDE { *dest = new T(*reinterpret_cast(src)); } virtual void clone(void *const *src, void **dest) CV_OVERRIDE { *dest = new T(**reinterpret_cast(src)); } virtual void move(void *const *src, void **dest) CV_OVERRIDE { (*reinterpret_cast(dest))->~T(); **reinterpret_cast(dest) = **reinterpret_cast(src); } virtual void *get_value(void **src) CV_OVERRIDE { return *src; } virtual const void *get_value(void *const *src) CV_OVERRIDE { return *src; } virtual void print(std::ostream &out, void *const *src) CV_OVERRIDE { 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; } } //! @endcond #endif // OPENCV_FLANN_ANY_H_