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