1 // This file is part of OpenCV project. 2 // It is subject to the license terms in the LICENSE file found in the top-level directory 3 // of this distribution and at http://opencv.org/license.html. 4 // 5 // Copyright (C) 2018 Intel Corporation 6 7 8 #ifndef OPENCV_GAPI_UTIL_ANY_HPP 9 #define OPENCV_GAPI_UTIL_ANY_HPP 10 11 #include <memory> 12 #include <type_traits> 13 #include <typeinfo> 14 #include <utility> 15 16 #include <opencv2/gapi/util/throw.hpp> 17 18 #if defined(_MSC_VER) 19 // disable MSVC warning on "multiple copy constructors specified" 20 # pragma warning(disable: 4521) 21 #endif 22 23 namespace cv 24 { 25 26 namespace internal 27 { 28 template <class T, class Source> 29 T down_cast(Source operand) 30 { 31 #if defined(__GXX_RTTI) || defined(_CPPRTTI) 32 return dynamic_cast<T>(operand); 33 #else 34 #warning used static cast instead of dynamic because RTTI is disabled 35 return static_cast<T>(operand); 36 #endif 37 } 38 } 39 40 namespace util 41 { 42 class bad_any_cast : public std::bad_cast 43 { 44 public: what() const45 virtual const char* what() const noexcept override 46 { 47 return "Bad any cast"; 48 } 49 }; 50 51 //modeled against C++17 std::any 52 53 class any 54 { 55 private: 56 struct holder; 57 using holder_ptr = std::unique_ptr<holder>; 58 struct holder 59 { 60 virtual holder_ptr clone() = 0; 61 virtual ~holder() = default; 62 }; 63 64 template <typename value_t> 65 struct holder_impl : holder 66 { 67 value_t v; 68 template<typename arg_t> holder_implcv::util::any::holder_impl69 holder_impl(arg_t&& a) : v(std::forward<arg_t>(a)) {} clonecv::util::any::holder_impl70 holder_ptr clone() override { return holder_ptr(new holder_impl (v));} 71 }; 72 73 holder_ptr hldr; 74 public: 75 template<class value_t> any(value_t && arg)76 any(value_t&& arg) : hldr(new holder_impl<typename std::decay<value_t>::type>( std::forward<value_t>(arg))) {} 77 any(any const & src)78 any(any const& src) : hldr( src.hldr ? src.hldr->clone() : nullptr) {} 79 //simple hack in order not to write enable_if<not any> for the template constructor any(any & src)80 any(any & src) : any (const_cast<any const&>(src)) {} 81 82 any() = default; 83 any(any&& ) = default; 84 85 any& operator=(any&&) = default; 86 operator =(any const & src)87 any& operator=(any const& src) 88 { 89 any copy(src); 90 swap(*this, copy); 91 return *this; 92 } 93 94 template<class value_t> 95 friend value_t* any_cast(any* operand); 96 97 template<class value_t> 98 friend const value_t* any_cast(const any* operand); 99 100 template<class value_t> 101 friend value_t& unsafe_any_cast(any& operand); 102 103 template<class value_t> 104 friend const value_t& unsafe_any_cast(const any& operand); 105 swap(any & lhs,any & rhs)106 friend void swap(any & lhs, any& rhs) 107 { 108 swap(lhs.hldr, rhs.hldr); 109 } 110 111 }; 112 113 template<class value_t> any_cast(any * operand)114 value_t* any_cast(any* operand) 115 { 116 auto casted = internal::down_cast<any::holder_impl<typename std::decay<value_t>::type> *>(operand->hldr.get()); 117 if (casted){ 118 return & (casted->v); 119 } 120 return nullptr; 121 } 122 123 template<class value_t> any_cast(const any * operand)124 const value_t* any_cast(const any* operand) 125 { 126 auto casted = internal::down_cast<any::holder_impl<typename std::decay<value_t>::type> *>(operand->hldr.get()); 127 if (casted){ 128 return & (casted->v); 129 } 130 return nullptr; 131 } 132 133 template<class value_t> any_cast(any & operand)134 value_t& any_cast(any& operand) 135 { 136 auto ptr = any_cast<value_t>(&operand); 137 if (ptr) 138 { 139 return *ptr; 140 } 141 142 throw_error(bad_any_cast()); 143 } 144 145 146 template<class value_t> any_cast(const any & operand)147 const value_t& any_cast(const any& operand) 148 { 149 auto ptr = any_cast<value_t>(&operand); 150 if (ptr) 151 { 152 return *ptr; 153 } 154 155 throw_error(bad_any_cast()); 156 } 157 158 template<class value_t> unsafe_any_cast(any & operand)159 inline value_t& unsafe_any_cast(any& operand) 160 { 161 #ifdef DEBUG 162 return any_cast<value_t>(operand); 163 #else 164 return static_cast<any::holder_impl<typename std::decay<value_t>::type> *>(operand.hldr.get())->v; 165 #endif 166 } 167 168 template<class value_t> unsafe_any_cast(const any & operand)169 inline const value_t& unsafe_any_cast(const any& operand) 170 { 171 #ifdef DEBUG 172 return any_cast<value_t>(operand); 173 #else 174 return static_cast<any::holder_impl<typename std::decay<value_t>::type> *>(operand.hldr.get())->v; 175 #endif 176 } 177 178 } // namespace util 179 } // namespace cv 180 181 #if defined(_MSC_VER) 182 // Enable "multiple copy constructors specified" back 183 # pragma warning(default: 4521) 184 #endif 185 186 #endif // OPENCV_GAPI_UTIL_ANY_HPP 187