include/opencv2/flann/any.h
Go to the documentation of this file.
00001 #ifndef OPENCV_FLANN_ANY_H_
00002 #define OPENCV_FLANN_ANY_H_
00003 /*
00004  * (C) Copyright Christopher Diggins 2005-2011
00005  * (C) Copyright Pablo Aguilar 2005
00006  * (C) Copyright Kevlin Henney 2001
00007  *
00008  * Distributed under the Boost Software License, Version 1.0. (See
00009  * accompanying file LICENSE_1_0.txt or copy at
00010  * http://www.boost.org/LICENSE_1_0.txt
00011  *
00012  * Adapted for FLANN by Marius Muja
00013  */
00014 
00015 #include "defines.h"
00016 #include <stdexcept>
00017 #include <ostream>
00018 #include <typeinfo>
00019 
00020 namespace cvflann
00021 {
00022 
00023 namespace anyimpl
00024 {
00025 
00026 struct bad_any_cast
00027 {
00028 };
00029 
00030 struct empty_any
00031 {
00032 };
00033 
00034 inline std::ostream& operator <<(std::ostream& out, const empty_any&)
00035 {
00036     out << "[empty_any]";
00037     return out;
00038 }
00039 
00040 struct base_any_policy
00041 {
00042     virtual void static_delete(void** x) = 0;
00043     virtual void copy_from_value(void const* src, void** dest) = 0;
00044     virtual void clone(void* const* src, void** dest) = 0;
00045     virtual void move(void* const* src, void** dest) = 0;
00046     virtual void* get_value(void** src) = 0;
00047     virtual ::size_t get_size() = 0;
00048     virtual const std::type_info& type() = 0;
00049     virtual void print(std::ostream& out, void* const* src) = 0;
00050 
00051 #ifdef OPENCV_CAN_BREAK_BINARY_COMPATIBILITY
00052     virtual ~base_any_policy() {}
00053 #endif
00054 };
00055 
00056 template<typename T>
00057 struct typed_base_any_policy : base_any_policy
00058 {
00059     virtual ::size_t get_size() { return sizeof(T); }
00060     virtual const std::type_info& type() { return typeid(T); }
00061 
00062 };
00063 
00064 template<typename T>
00065 struct small_any_policy : typed_base_any_policy<T>
00066 {
00067     virtual void static_delete(void**) { }
00068     virtual void copy_from_value(void const* src, void** dest)
00069     {
00070         new (dest) T(* reinterpret_cast<T const*>(src));
00071     }
00072     virtual void clone(void* const* src, void** dest) { *dest = *src; }
00073     virtual void move(void* const* src, void** dest) { *dest = *src; }
00074     virtual void* get_value(void** src) { return reinterpret_cast<void*>(src); }
00075     virtual void print(std::ostream& out, void* const* src) { out << *reinterpret_cast<T const*>(src); }
00076 };
00077 
00078 template<typename T>
00079 struct big_any_policy : typed_base_any_policy<T>
00080 {
00081     virtual void static_delete(void** x)
00082     {
00083         if (* x) delete (* reinterpret_cast<T**>(x)); *x = NULL;
00084     }
00085     virtual void copy_from_value(void const* src, void** dest)
00086     {
00087         *dest = new T(*reinterpret_cast<T const*>(src));
00088     }
00089     virtual void clone(void* const* src, void** dest)
00090     {
00091         *dest = new T(**reinterpret_cast<T* const*>(src));
00092     }
00093     virtual void move(void* const* src, void** dest)
00094     {
00095         (*reinterpret_cast<T**>(dest))->~T();
00096         **reinterpret_cast<T**>(dest) = **reinterpret_cast<T* const*>(src);
00097     }
00098     virtual void* get_value(void** src) { return *src; }
00099     virtual void print(std::ostream& out, void* const* src) { out << *reinterpret_cast<T const*>(*src); }
00100 };
00101 
00102 template<> inline void big_any_policy<flann_centers_init_t>::print(std::ostream& out, void* const* src)
00103 {
00104     out << int(*reinterpret_cast<flann_centers_init_t const*>(*src));
00105 }
00106 
00107 template<> inline void big_any_policy<flann_algorithm_t>::print(std::ostream& out, void* const* src)
00108 {
00109     out << int(*reinterpret_cast<flann_algorithm_t const*>(*src));
00110 }
00111 
00112 template<typename T>
00113 struct choose_policy
00114 {
00115     typedef big_any_policy<T> type;
00116 };
00117 
00118 template<typename T>
00119 struct choose_policy<T*>
00120 {
00121     typedef small_any_policy<T*> type;
00122 };
00123 
00124 struct any;
00125 
00128 template<>
00129 struct choose_policy<any>
00130 {
00131     typedef void type;
00132 };
00133 
00135 #define SMALL_POLICY(TYPE) \
00136     template<> \
00137     struct choose_policy<TYPE> { typedef small_any_policy<TYPE> type; \
00138     }
00139 
00140 SMALL_POLICY(signed char);
00141 SMALL_POLICY(unsigned char);
00142 SMALL_POLICY(signed short);
00143 SMALL_POLICY(unsigned short);
00144 SMALL_POLICY(signed int);
00145 SMALL_POLICY(unsigned int);
00146 SMALL_POLICY(signed long);
00147 SMALL_POLICY(unsigned long);
00148 SMALL_POLICY(float);
00149 SMALL_POLICY(bool);
00150 
00151 #undef SMALL_POLICY
00152 
00154 template<typename T>
00155 base_any_policy* get_policy()
00156 {
00157     static typename choose_policy<T>::type policy;
00158     return &policy;
00159 }
00160 } // namespace anyimpl
00161 
00162 struct any
00163 {
00164 private:
00165     // fields
00166     anyimpl::base_any_policy* policy;
00167     void* object;
00168 
00169 public:
00171     template <typename T>
00172     any(const T& x)
00173         : policy(anyimpl::get_policy<anyimpl::empty_any>()), object(NULL)
00174     {
00175         assign(x);
00176     }
00177 
00179     any()
00180         : policy(anyimpl::get_policy<anyimpl::empty_any>()), object(NULL)
00181     { }
00182 
00184     any(const char* x)
00185         : policy(anyimpl::get_policy<anyimpl::empty_any>()), object(NULL)
00186     {
00187         assign(x);
00188     }
00189 
00191     any(const any& x)
00192         : policy(anyimpl::get_policy<anyimpl::empty_any>()), object(NULL)
00193     {
00194         assign(x);
00195     }
00196 
00198     ~any()
00199     {
00200         policy->static_delete(&object);
00201     }
00202 
00204     any& assign(const any& x)
00205     {
00206         reset();
00207         policy = x.policy;
00208         policy->clone(&x.object, &object);
00209         return *this;
00210     }
00211 
00213     template <typename T>
00214     any& assign(const T& x)
00215     {
00216         reset();
00217         policy = anyimpl::get_policy<T>();
00218         policy->copy_from_value(&x, &object);
00219         return *this;
00220     }
00221 
00223     template<typename T>
00224     any& operator=(const T& x)
00225     {
00226         return assign(x);
00227     }
00228 
00231     any& operator=(const char* x)
00232     {
00233         return assign(x);
00234     }
00235 
00237     any& swap(any& x)
00238     {
00239         std::swap(policy, x.policy);
00240         std::swap(object, x.object);
00241         return *this;
00242     }
00243 
00245     template<typename T>
00246     T& cast()
00247     {
00248         if (policy->type() != typeid(T)) throw anyimpl::bad_any_cast();
00249         T* r = reinterpret_cast<T*>(policy->get_value(&object));
00250         return *r;
00251     }
00252 
00254     template<typename T>
00255     const T& cast() const
00256     {
00257         if (policy->type() != typeid(T)) throw anyimpl::bad_any_cast();
00258         void* obj = const_cast<void*>(object);
00259         T* r = reinterpret_cast<T*>(policy->get_value(&obj));
00260         return *r;
00261     }
00262 
00264     bool empty() const
00265     {
00266         return policy->type() == typeid(anyimpl::empty_any);
00267     }
00268 
00270     void reset()
00271     {
00272         policy->static_delete(&object);
00273         policy = anyimpl::get_policy<anyimpl::empty_any>();
00274     }
00275 
00277     bool compatible(const any& x) const
00278     {
00279         return policy->type() == x.policy->type();
00280     }
00281 
00283     template<typename T>
00284     bool has_type()
00285     {
00286         return policy->type() == typeid(T);
00287     }
00288 
00289     const std::type_info& type() const
00290     {
00291         return policy->type();
00292     }
00293 
00294     friend std::ostream& operator <<(std::ostream& out, const any& any_val);
00295 };
00296 
00297 inline std::ostream& operator <<(std::ostream& out, const any& any_val)
00298 {
00299     any_val.policy->print(out,&any_val.object);
00300     return out;
00301 }
00302 
00303 }
00304 
00305 #endif // OPENCV_FLANN_ANY_H_