1 // Copyright Daniel Wallin 2006. Use, modification and distribution is
2 // subject to the Boost Software License, Version 1.0. (See accompanying
3 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
4 
5 //
6 // 2009.10.21 TDS remove depenency on boost::python::detail::referent_storage
7 //
8 #ifndef BOOST_PARAMETER_MAYBE_091021_HPP
9 # define BOOST_PARAMETER_MAYBE_091021_HPP
10 
11 # include <boost/mpl/if.hpp>
12 # include <boost/mpl/identity.hpp>
13 # include <boost/type_traits/is_reference.hpp>
14 # include <boost/type_traits/add_reference.hpp>
15 # include <boost/optional.hpp>
16 # include <boost/aligned_storage.hpp>
17 # include <boost/type_traits/remove_cv.hpp>
18 # include <boost/type_traits/add_const.hpp>
19 # include <boost/parameter/aux_/is_maybe.hpp>
20 
21 namespace boost { namespace parameter { namespace aux {
22 
23 template <class T> struct referent_size;
24 
25 template <class T>
26 struct referent_size<T&>
27 {
28   BOOST_STATIC_CONSTANT(std::size_t, value = sizeof(T));
29 };
30 
31 // A metafunction returning a POD type which can store U, where T ==
32 // U&. If T is not a reference type, returns a POD which can store T.
33 template <class T>
34 struct referent_storage
35 {
36   typedef typename boost::aligned_storage<
37     referent_size<T>::value
38     >::type type;
39 };
40 
41 template <class T>
42 struct maybe : maybe_base
43 {
44     typedef typename add_reference<
45 # if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
46         T const
47 # else
48         typename add_const<T>::type
49 # endif
50     >::type reference;
51 
52     typedef typename remove_cv<
53         BOOST_DEDUCED_TYPENAME remove_reference<reference>::type
54     >::type non_cv_value;
55 
maybeboost::parameter::aux::maybe56     explicit maybe(T value_)
57       : value(value_)
58       , constructed(false)
59     {}
60 
maybeboost::parameter::aux::maybe61     maybe()
62       : constructed(false)
63     {}
64 
~maybeboost::parameter::aux::maybe65     ~maybe()
66     {
67         if (constructed)
68             this->destroy();
69     }
70 
constructboost::parameter::aux::maybe71     reference construct(reference value_) const
72     {
73         return value_;
74     }
75 
76     template <class U>
construct2boost::parameter::aux::maybe77     reference construct2(U const& value_) const
78     {
79         new (m_storage.address()) non_cv_value(value_);
80         constructed = true;
81         return *(non_cv_value*)m_storage.address();
82     }
83 
84     template <class U>
constructboost::parameter::aux::maybe85     reference construct(U const& value_) const
86     {
87         return this->construct2(value_);
88     }
89 
destroyboost::parameter::aux::maybe90     void destroy()
91     {
92         ((non_cv_value*)m_storage.address())->~non_cv_value();
93     }
94 
95     typedef reference(maybe<T>::*safe_bool)() const;
96 
operator safe_boolboost::parameter::aux::maybe97     operator safe_bool() const
98     {
99         return value ? &maybe<T>::get : 0 ;
100     }
101 
getboost::parameter::aux::maybe102     reference get() const
103     {
104         return value.get();
105     }
106 
107 private:
108     boost::optional<T> value;
109     mutable bool constructed;
110 
111 
112     mutable typename referent_storage<
113         reference
114     >::type m_storage;
115 };
116 
117 }}} // namespace boost::parameter::aux
118 
119 #endif // BOOST_PARAMETER_MAYBE_060211_HPP
120 
121