]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | // Boost.TypeErasure library |
2 | // | |
3 | // Copyright 2011 Steven Watanabe | |
4 | // | |
5 | // Distributed under the Boost Software License Version 1.0. (See | |
6 | // accompanying file LICENSE_1_0.txt or copy at | |
7 | // http://www.boost.org/LICENSE_1_0.txt) | |
8 | // | |
9 | // $Id$ | |
10 | ||
11 | #ifndef BOOST_TYPE_ERASURE_ANY_CAST_HPP_INCLUDED | |
12 | #define BOOST_TYPE_ERASURE_ANY_CAST_HPP_INCLUDED | |
13 | ||
14 | #include <stdexcept> | |
15 | #include <boost/throw_exception.hpp> | |
16 | #include <boost/type_traits/add_const.hpp> | |
17 | #include <boost/type_traits/is_pointer.hpp> | |
18 | #include <boost/type_traits/remove_cv.hpp> | |
19 | #include <boost/type_traits/remove_reference.hpp> | |
20 | #include <boost/type_traits/remove_pointer.hpp> | |
21 | #include <boost/type_traits/is_void.hpp> | |
22 | #include <boost/mpl/assert.hpp> | |
23 | #include <boost/mpl/bool.hpp> | |
24 | #include <boost/type_erasure/any.hpp> | |
25 | #include <boost/type_erasure/builtin.hpp> | |
26 | #include <boost/type_erasure/exception.hpp> | |
27 | #include <boost/type_erasure/detail/access.hpp> | |
28 | ||
29 | namespace boost { | |
30 | namespace type_erasure { | |
31 | ||
32 | namespace detail { | |
33 | ||
34 | template<class Concept, class T> | |
35 | void* get_pointer(::boost::type_erasure::any<Concept, T>& arg) | |
36 | { | |
37 | return ::boost::type_erasure::detail::access::data(arg).data; | |
38 | } | |
39 | ||
40 | template<class Concept, class T> | |
41 | const void* get_pointer(const ::boost::type_erasure::any<Concept, T>& arg) | |
42 | { | |
43 | return ::boost::type_erasure::detail::access::data(arg).data; | |
44 | } | |
45 | ||
46 | template<class Concept, class T> | |
47 | void* get_pointer(::boost::type_erasure::any<Concept, T&>& arg) | |
48 | { | |
49 | return ::boost::type_erasure::detail::access::data(arg).data; | |
50 | } | |
51 | ||
52 | template<class Concept, class T> | |
53 | void* get_pointer(const ::boost::type_erasure::any<Concept, T&>& arg) | |
54 | { | |
55 | return ::boost::type_erasure::detail::access::data(arg).data; | |
56 | } | |
57 | ||
58 | template<class Concept, class T> | |
59 | const void* get_pointer(::boost::type_erasure::any<Concept, const T&>& arg) | |
60 | { | |
61 | return ::boost::type_erasure::detail::access::data(arg).data; | |
62 | } | |
63 | ||
64 | template<class Concept, class T> | |
65 | const void* get_pointer(const ::boost::type_erasure::any<Concept, const T&>& arg) | |
66 | { | |
67 | return ::boost::type_erasure::detail::access::data(arg).data; | |
68 | } | |
69 | ||
70 | template<class T, class Concept, class Tag> | |
71 | bool check_any_cast(const any<Concept, Tag>&, ::boost::mpl::true_) | |
72 | { | |
73 | return true; | |
74 | } | |
75 | ||
76 | template<class T, class Concept, class Tag> | |
77 | bool check_any_cast(const any<Concept, Tag>& arg, ::boost::mpl::false_) | |
78 | { | |
79 | typedef typename ::boost::remove_cv< | |
80 | typename ::boost::remove_reference<Tag>::type | |
81 | >::type tag_type; | |
82 | return ::boost::type_erasure::detail::access::table(arg) | |
83 | .template find<typeid_<tag_type> >()() == typeid(T); | |
84 | } | |
85 | ||
86 | template<class T, class Concept, class Tag> | |
87 | bool check_any_cast(const any<Concept, Tag>& arg) | |
88 | { | |
89 | return ::boost::type_erasure::detail::check_any_cast<T>( | |
90 | arg, ::boost::is_void<typename ::boost::remove_reference<T>::type>()); | |
91 | } | |
92 | ||
93 | } | |
94 | ||
95 | /** | |
96 | * Attempts to extract the object that @c arg holds. | |
97 | * If casting to a pointer fails, \any_cast returns | |
98 | * a null pointer. Casting to @c void* always succeeds | |
99 | * and returns the address of stored object. | |
100 | * | |
101 | * \code | |
102 | * any<mpl::vector<typeid_<>, copy_constructible<> > > x(1); | |
103 | * any_cast<int>(x); // returns 1 | |
104 | * any_cast<int&>(x); // returns a reference to the contents of x | |
105 | * any_cast<double>(x); // throws bad_any_cast | |
106 | * any_cast<int*>(&x); // returns a pointer to the contents of x | |
107 | * any_cast<void*>(&x); // returns a pointer to the contents of x | |
108 | * any_cast<double*>(&x); // returns NULL | |
109 | * \endcode | |
110 | * | |
111 | * \pre if @c arg is a pointer, @c T must be a pointer type. | |
112 | * \pre @c Concept must contain @ref typeid_<tt><Tag></tt>. | |
113 | * | |
114 | * \throws bad_any_cast if @c arg doesn't contain | |
115 | * an object of type @c T and we're casting | |
116 | * to a value or reference. | |
117 | */ | |
118 | template<class T, class Concept, class Tag> | |
119 | T any_cast(any<Concept, Tag>& arg) | |
120 | { | |
121 | if(::boost::type_erasure::detail::check_any_cast<T>(arg)) { | |
122 | return *static_cast< | |
123 | typename ::boost::remove_reference< | |
124 | typename ::boost::add_const<T>::type | |
125 | >::type* | |
126 | >(::boost::type_erasure::detail::get_pointer(arg)); | |
127 | } else { | |
128 | BOOST_THROW_EXCEPTION(::boost::type_erasure::bad_any_cast()); | |
129 | } | |
130 | } | |
131 | ||
132 | /** \overload */ | |
133 | template<class T, class Concept, class Tag> | |
134 | T any_cast(const any<Concept, Tag>& arg) | |
135 | { | |
136 | if(::boost::type_erasure::detail::check_any_cast<T>(arg)) { | |
137 | return *static_cast< | |
138 | typename ::boost::remove_reference< | |
139 | typename ::boost::add_const<T>::type | |
140 | >::type* | |
141 | >(::boost::type_erasure::detail::get_pointer(arg)); | |
142 | } else { | |
143 | BOOST_THROW_EXCEPTION(::boost::type_erasure::bad_any_cast()); | |
144 | } | |
145 | } | |
146 | ||
147 | /** \overload */ | |
148 | template<class T, class Concept, class Tag> | |
149 | T any_cast(any<Concept, Tag>* arg) | |
150 | { | |
151 | BOOST_MPL_ASSERT((::boost::is_pointer<T>)); | |
152 | if(::boost::type_erasure::detail::check_any_cast< | |
153 | typename ::boost::remove_pointer<T>::type>(*arg)) { | |
154 | return static_cast< | |
155 | typename ::boost::remove_pointer<T>::type*>( | |
156 | ::boost::type_erasure::detail::get_pointer(*arg)); | |
157 | } else { | |
158 | return 0; | |
159 | } | |
160 | } | |
161 | ||
162 | /** \overload */ | |
163 | template<class T, class Concept, class Tag> | |
164 | T any_cast(const any<Concept, Tag>* arg) | |
165 | { | |
166 | BOOST_MPL_ASSERT((::boost::is_pointer<T>)); | |
167 | if(::boost::type_erasure::detail::check_any_cast< | |
168 | typename ::boost::remove_pointer<T>::type>(*arg)) { | |
169 | return static_cast< | |
170 | typename ::boost::remove_pointer<T>::type*>( | |
171 | ::boost::type_erasure::detail::get_pointer(*arg)); | |
172 | } else { | |
173 | return 0; | |
174 | } | |
175 | } | |
176 | ||
177 | } | |
178 | } | |
179 | ||
180 | #endif |