1 | // Copyright Daniel Wallin 2006. |
2 | // Distributed under the Boost Software License, Version 1.0. |
3 | // (See accompanying file LICENSE_1_0.txt or copy at |
4 | // http://www.boost.org/LICENSE_1_0.txt) |
5 | |
6 | // |
7 | // 2009.10.21 TDS remove depenency on boost::python::detail::referent_storage |
8 | // |
9 | #ifndef BOOST_PARAMETER_MAYBE_091021_HPP |
10 | #define BOOST_PARAMETER_MAYBE_091021_HPP |
11 | |
12 | namespace boost { namespace parameter { namespace aux { |
13 | |
14 | template <typename T> |
15 | struct referent_size; |
16 | }}} // namespace boost::parameter::aux |
17 | |
18 | #include <boost/parameter/config.hpp> |
19 | |
20 | namespace boost { namespace parameter { namespace aux { |
21 | |
22 | template <typename T> |
23 | struct referent_size<T&> |
24 | { |
25 | BOOST_STATIC_CONSTANT(::std::size_t, value = sizeof(T)); |
26 | }; |
27 | }}} // namespace boost::parameter::aux |
28 | |
29 | #include <boost/type_traits/aligned_storage.hpp> |
30 | |
31 | namespace boost { namespace parameter { namespace aux { |
32 | |
33 | // A metafunction returning a POD type which can store U, where T == U&. |
34 | // If T is not a reference type, returns a POD which can store T. |
35 | template <typename T> |
36 | struct referent_storage |
37 | : ::boost::aligned_storage< |
38 | ::boost::parameter::aux::referent_size<T>::value |
39 | > |
40 | { |
41 | }; |
42 | }}} // namespace boost::parameter::aux |
43 | |
44 | #include <boost/parameter/aux_/is_maybe.hpp> |
45 | #include <boost/optional/optional.hpp> |
46 | |
47 | #if defined(BOOST_PARAMETER_CAN_USE_MP11) |
48 | #include <type_traits> |
49 | #else // !defined(BOOST_PARAMETER_CAN_USE_MP11) |
50 | #include <boost/type_traits/add_lvalue_reference.hpp> |
51 | #include <boost/type_traits/remove_cv.hpp> |
52 | #if !BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x564)) |
53 | #include <boost/type_traits/add_const.hpp> |
54 | #endif |
55 | #endif // BOOST_PARAMETER_CAN_USE_MP11 |
56 | |
57 | namespace boost { namespace parameter { namespace aux { |
58 | |
59 | template <typename T> |
60 | struct maybe : ::boost::parameter::aux::maybe_base |
61 | { |
62 | #if defined(BOOST_PARAMETER_CAN_USE_MP11) |
63 | typedef typename ::std::add_lvalue_reference< |
64 | typename ::std::add_const<T>::type |
65 | #else // !defined(BOOST_PARAMETER_CAN_USE_MP11) |
66 | typedef typename ::boost::add_lvalue_reference< |
67 | #if BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x564)) |
68 | T const |
69 | #else |
70 | typename ::boost::add_const<T>::type |
71 | #endif |
72 | #endif // BOOST_PARAMETER_CAN_USE_MP11 |
73 | >::type reference; |
74 | |
75 | #if defined(BOOST_PARAMETER_CAN_USE_MP11) |
76 | typedef typename ::std::remove_cv< |
77 | typename ::std::remove_reference<reference>::type |
78 | #else |
79 | typedef typename ::boost::remove_cv< |
80 | BOOST_DEDUCED_TYPENAME ::boost::remove_reference<reference>::type |
81 | #endif |
82 | >::type non_cv_value; |
83 | |
84 | inline explicit maybe(T value_) : value(value_), constructed(false) |
85 | { |
86 | } |
87 | |
88 | inline maybe() : value(), constructed(false) |
89 | { |
90 | } |
91 | |
92 | ~maybe() |
93 | { |
94 | if (this->constructed) |
95 | { |
96 | this->destroy(); |
97 | } |
98 | } |
99 | |
100 | inline reference construct(reference value_) const |
101 | { |
102 | return value_; |
103 | } |
104 | |
105 | template <typename U> |
106 | reference construct2(U const& value_) const |
107 | { |
108 | new (this->m_storage.address()) non_cv_value(value_); |
109 | this->constructed = true; |
110 | return *reinterpret_cast<non_cv_value*>( |
111 | this->m_storage.address() |
112 | ); |
113 | } |
114 | |
115 | template <typename U> |
116 | inline reference construct(U const& value_) const |
117 | { |
118 | return this->construct2(value_); |
119 | } |
120 | |
121 | void destroy() |
122 | { |
123 | reinterpret_cast<non_cv_value*>( |
124 | this->m_storage.address() |
125 | )->~non_cv_value(); |
126 | } |
127 | |
128 | typedef reference( |
129 | ::boost::parameter::aux::maybe<T>::*safe_bool |
130 | )() const; |
131 | |
132 | inline operator safe_bool() const |
133 | { |
134 | return this->value ? &::boost::parameter::aux::maybe<T>::get : 0; |
135 | } |
136 | |
137 | inline reference get() const |
138 | { |
139 | return this->value.get(); |
140 | } |
141 | |
142 | private: |
143 | ::boost::optional<T> value; |
144 | mutable bool constructed; |
145 | mutable typename ::boost::parameter::aux |
146 | ::referent_storage<reference>::type m_storage; |
147 | }; |
148 | }}} // namespace boost::parameter::aux |
149 | |
150 | #endif // include guard |
151 | |
152 | |