summaryrefslogtreecommitdiffstats
blob: ced1cdd90527e8bc66497701a2e94a915aab6d4c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2009-2012.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/move for documentation.
//
//////////////////////////////////////////////////////////////////////////////

//! \file

#ifndef BOOST_MOVE_MOVE_TRAITS_HPP
#define BOOST_MOVE_MOVE_TRAITS_HPP

#include <boost/move/detail/config_begin.hpp>
#include <boost/type_traits/has_trivial_destructor.hpp>
#include <boost/type_traits/is_nothrow_move_constructible.hpp>
#include <boost/type_traits/is_nothrow_move_assignable.hpp>
#include <boost/move/detail/meta_utils.hpp>

#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
#include <boost/move/core.hpp>
#endif

namespace boost {

//! If this trait yields to true
//! (<i>has_trivial_destructor_after_move &lt;T&gt;::value == true</i>)
//! means that if T is used as argument of a move construction/assignment,
//! there is no need to call T's destructor.
//! This optimization tipically is used to improve containers' performance.
//!
//! By default this trait is true if the type has trivial destructor,
//! every class should specialize this trait if it wants to improve performance
//! when inserted in containers.
template <class T>
struct has_trivial_destructor_after_move
   : ::boost::has_trivial_destructor<T>
{};

//! By default this traits returns
//! <pre>boost::is_nothrow_move_constructible<T>::value && boost::is_nothrow_move_assignable<T>::value </pre>.
//! Classes with non-throwing move constructor
//! and assignment can specialize this trait to obtain some performance improvements.
template <class T>
struct has_nothrow_move
   : public ::boost::move_detail::integral_constant
      < bool
      , boost::is_nothrow_move_constructible<T>::value &&
        boost::is_nothrow_move_assignable<T>::value
      >
{};

namespace move_detail {

// Code from Jeffrey Lee Hellrung, many thanks

#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
   template< class T> struct forward_type { typedef T type; };
#else // #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
   template< class T>
   struct forward_type
   { typedef const T &type; };

   template< class T>
   struct forward_type< boost::rv<T> >
   { typedef T type; };
#endif // #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES

template< class T > struct is_rvalue_reference : ::boost::move_detail::integral_constant<bool, false> { };
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
   template< class T > struct is_rvalue_reference< T&& > : ::boost::move_detail::integral_constant<bool, true> { };
#else // #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
   template< class T > struct is_rvalue_reference< boost::rv<T>& >
      :  ::boost::move_detail::integral_constant<bool, true>
   {};

   template< class T > struct is_rvalue_reference< const boost::rv<T>& >
      : ::boost::move_detail::integral_constant<bool, true>
   {};
#endif // #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES

#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
   template< class T > struct add_rvalue_reference { typedef T&& type; };
#else // #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
   namespace detail_add_rvalue_reference
   {
      template< class T
              , bool emulation = ::boost::has_move_emulation_enabled<T>::value
              , bool rv        = ::boost::move_detail::is_rv<T>::value  >
      struct add_rvalue_reference_impl { typedef T type; };

      template< class T, bool emulation>
      struct add_rvalue_reference_impl< T, emulation, true > { typedef T & type; };

      template< class T, bool rv >
      struct add_rvalue_reference_impl< T, true, rv > { typedef ::boost::rv<T>& type; };
   } // namespace detail_add_rvalue_reference

   template< class T >
   struct add_rvalue_reference
      : detail_add_rvalue_reference::add_rvalue_reference_impl<T>
   { };

   template< class T >
   struct add_rvalue_reference<T &>
   {  typedef T & type; };

#endif // #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES

template< class T > struct remove_rvalue_reference { typedef T type; };

#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
   template< class T > struct remove_rvalue_reference< T&& >                  { typedef T type; };
#else // #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
   template< class T > struct remove_rvalue_reference< rv<T> >                { typedef T type; };
   template< class T > struct remove_rvalue_reference< const rv<T> >          { typedef T type; };
   template< class T > struct remove_rvalue_reference< volatile rv<T> >       { typedef T type; };
   template< class T > struct remove_rvalue_reference< const volatile rv<T> > { typedef T type; };
   template< class T > struct remove_rvalue_reference< rv<T>& >               { typedef T type; };
   template< class T > struct remove_rvalue_reference< const rv<T>& >         { typedef T type; };
   template< class T > struct remove_rvalue_reference< volatile rv<T>& >      { typedef T type; };
   template< class T > struct remove_rvalue_reference< const volatile rv<T>& >{ typedef T type; };
#endif // #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES

template <typename T>
typename boost::move_detail::add_rvalue_reference<T>::type declval();

}  //move_detail {

// Ideas from Boost.Move review, Jeffrey Lee Hellrung:
//
//- TypeTraits metafunctions is_lvalue_reference, add_lvalue_reference, and remove_lvalue_reference ?
//  Perhaps add_reference and remove_reference can be modified so that they behave wrt emulated rvalue
//  references the same as wrt real rvalue references, i.e., add_reference< rv<T>& > -> T& rather than
//  rv<T>& (since T&& & -> T&).
//
//- Add'l TypeTraits has_[trivial_]move_{constructor,assign}...?
//
//- An as_lvalue(T& x) function, which amounts to an identity operation in C++0x, but strips emulated
//  rvalue references in C++03.  This may be necessary to prevent "accidental moves".


}  //namespace boost {

#include <boost/move/detail/config_end.hpp>

#endif //#ifndef BOOST_MOVE_MOVE_TRAITS_HPP