1 //////////////////////////////////////////////////////////////////////////////
2 //
3 // (C) Copyright Ion Gaztanaga 2009-2012.
4 // Distributed under the Boost Software License, Version 1.0.
5 // (See accompanying file LICENSE_1_0.txt or copy at
6 // http://www.boost.org/LICENSE_1_0.txt)
7 //
8 // See http://www.boost.org/libs/move for documentation.
9 //
10 //////////////////////////////////////////////////////////////////////////////
11 
12 //! \file
13 
14 #ifndef BOOST_MOVE_MOVE_TRAITS_HPP
15 #define BOOST_MOVE_MOVE_TRAITS_HPP
16 
17 #include <boost/move/detail/config_begin.hpp>
18 #include <boost/type_traits/has_trivial_destructor.hpp>
19 #include <boost/type_traits/is_nothrow_move_constructible.hpp>
20 #include <boost/type_traits/is_nothrow_move_assignable.hpp>
21 #include <boost/move/detail/meta_utils.hpp>
22 
23 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
24 #include <boost/move/core.hpp>
25 #endif
26 
27 namespace boost {
28 
29 //! If this trait yields to true
30 //! (<i>has_trivial_destructor_after_move &lt;T&gt;::value == true</i>)
31 //! means that if T is used as argument of a move construction/assignment,
32 //! there is no need to call T's destructor.
33 //! This optimization tipically is used to improve containers' performance.
34 //!
35 //! By default this trait is true if the type has trivial destructor,
36 //! every class should specialize this trait if it wants to improve performance
37 //! when inserted in containers.
38 template <class T>
39 struct has_trivial_destructor_after_move
40    : ::boost::has_trivial_destructor<T>
41 {};
42 
43 //! By default this traits returns
44 //! <pre>boost::is_nothrow_move_constructible<T>::value && boost::is_nothrow_move_assignable<T>::value </pre>.
45 //! Classes with non-throwing move constructor
46 //! and assignment can specialize this trait to obtain some performance improvements.
47 template <class T>
48 struct has_nothrow_move
49    : public ::boost::move_detail::integral_constant
50       < bool
51       , boost::is_nothrow_move_constructible<T>::value &&
52         boost::is_nothrow_move_assignable<T>::value
53       >
54 {};
55 
56 namespace move_detail {
57 
58 // Code from Jeffrey Lee Hellrung, many thanks
59 
60 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
61    template< class T> struct forward_type { typedef T type; };
62 #else // #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
63    template< class T>
64    struct forward_type
65    { typedef const T &type; };
66 
67    template< class T>
68    struct forward_type< boost::rv<T> >
69    { typedef T type; };
70 #endif // #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
71 
72 template< class T > struct is_rvalue_reference : ::boost::move_detail::integral_constant<bool, false> { };
73 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
74    template< class T > struct is_rvalue_reference< T&& > : ::boost::move_detail::integral_constant<bool, true> { };
75 #else // #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
76    template< class T > struct is_rvalue_reference< boost::rv<T>& >
77       :  ::boost::move_detail::integral_constant<bool, true>
78    {};
79 
80    template< class T > struct is_rvalue_reference< const boost::rv<T>& >
81       : ::boost::move_detail::integral_constant<bool, true>
82    {};
83 #endif // #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
84 
85 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
86    template< class T > struct add_rvalue_reference { typedef T&& type; };
87 #else // #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
88    namespace detail_add_rvalue_reference
89    {
90       template< class T
91               , bool emulation = ::boost::has_move_emulation_enabled<T>::value
92               , bool rv        = ::boost::move_detail::is_rv<T>::value  >
93       struct add_rvalue_reference_impl { typedef T type; };
94 
95       template< class T, bool emulation>
96       struct add_rvalue_reference_impl< T, emulation, true > { typedef T & type; };
97 
98       template< class T, bool rv >
99       struct add_rvalue_reference_impl< T, true, rv > { typedef ::boost::rv<T>& type; };
100    } // namespace detail_add_rvalue_reference
101 
102    template< class T >
103    struct add_rvalue_reference
104       : detail_add_rvalue_reference::add_rvalue_reference_impl<T>
105    { };
106 
107    template< class T >
108    struct add_rvalue_reference<T &>
109    {  typedef T & type; };
110 
111 #endif // #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
112 
113 template< class T > struct remove_rvalue_reference { typedef T type; };
114 
115 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
116    template< class T > struct remove_rvalue_reference< T&& >                  { typedef T type; };
117 #else // #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
118    template< class T > struct remove_rvalue_reference< rv<T> >                { typedef T type; };
119    template< class T > struct remove_rvalue_reference< const rv<T> >          { typedef T type; };
120    template< class T > struct remove_rvalue_reference< volatile rv<T> >       { typedef T type; };
121    template< class T > struct remove_rvalue_reference< const volatile rv<T> > { typedef T type; };
122    template< class T > struct remove_rvalue_reference< rv<T>& >               { typedef T type; };
123    template< class T > struct remove_rvalue_reference< const rv<T>& >         { typedef T type; };
124    template< class T > struct remove_rvalue_reference< volatile rv<T>& >      { typedef T type; };
125    template< class T > struct remove_rvalue_reference< const volatile rv<T>& >{ typedef T type; };
126 #endif // #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
127 
128 template <typename T>
129 typename boost::move_detail::add_rvalue_reference<T>::type declval();
130 
131 }  //move_detail {
132 
133 // Ideas from Boost.Move review, Jeffrey Lee Hellrung:
134 //
135 //- TypeTraits metafunctions is_lvalue_reference, add_lvalue_reference, and remove_lvalue_reference ?
136 //  Perhaps add_reference and remove_reference can be modified so that they behave wrt emulated rvalue
137 //  references the same as wrt real rvalue references, i.e., add_reference< rv<T>& > -> T& rather than
138 //  rv<T>& (since T&& & -> T&).
139 //
140 //- Add'l TypeTraits has_[trivial_]move_{constructor,assign}...?
141 //
142 //- An as_lvalue(T& x) function, which amounts to an identity operation in C++0x, but strips emulated
143 //  rvalue references in C++03.  This may be necessary to prevent "accidental moves".
144 
145 
146 }  //namespace boost {
147 
148 #include <boost/move/detail/config_end.hpp>
149 
150 #endif //#ifndef BOOST_MOVE_MOVE_TRAITS_HPP
151