100.00% Lines (7/7) 100.00% Functions (3/3)
TLA Baseline Branch
Line Hits Code Line Hits Code
1   // 1   //
2   // Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com) 2   // Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com)
3   // 3   //
4   // Distributed under the Boost Software License, Version 1.0. (See accompanying 4   // Distributed under the Boost Software License, Version 1.0. (See accompanying
5   // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 5   // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6   // 6   //
7   // Official repository: https://github.com/boostorg/json 7   // Official repository: https://github.com/boostorg/json
8   // 8   //
9   9  
10   #ifndef BOOST_JSON_PILFER_HPP 10   #ifndef BOOST_JSON_PILFER_HPP
11   #define BOOST_JSON_PILFER_HPP 11   #define BOOST_JSON_PILFER_HPP
12   12  
13   #include <boost/core/detail/static_assert.hpp> 13   #include <boost/core/detail/static_assert.hpp>
14   #include <boost/json/detail/config.hpp> 14   #include <boost/json/detail/config.hpp>
15   #include <type_traits> 15   #include <type_traits>
16   #include <utility> 16   #include <utility>
17   17  
18   /* 18   /*
19   Implements "pilfering" from P0308R0 19   Implements "pilfering" from P0308R0
20   20  
21   @see 21   @see
22   http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0308r0.html 22   http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0308r0.html
23   */ 23   */
24   24  
25   namespace boost { 25   namespace boost {
26   namespace json { 26   namespace json {
27   27  
28   /** Tag wrapper to specify pilfer-construction. 28   /** Tag wrapper to specify pilfer-construction.
29   29  
30   This wrapper is used to specify a pilfer constructor 30   This wrapper is used to specify a pilfer constructor
31   overload. 31   overload.
32   32  
33   @par Example 33   @par Example
34   34  
35   A pilfer constructor accepts a single argument 35   A pilfer constructor accepts a single argument
36   of type @ref pilfered and throws nothing: 36   of type @ref pilfered and throws nothing:
37   37  
38   @code 38   @code
39   struct T 39   struct T
40   { 40   {
41   T( pilfered<T> ) noexcept; 41   T( pilfered<T> ) noexcept;
42   }; 42   };
43   @endcode 43   @endcode
44   44  
45   @note 45   @note
46   46  
47   The constructor should not be marked explicit. 47   The constructor should not be marked explicit.
48   48  
49   @see @ref pilfer, @ref is_pilfer_constructible, 49   @see @ref pilfer, @ref is_pilfer_constructible,
50   <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0308r0.html"> 50   <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0308r0.html">
51   Valueless Variants Considered Harmful</a> 51   Valueless Variants Considered Harmful</a>
52   */ 52   */
53   template<class T> 53   template<class T>
54   class pilfered 54   class pilfered
55   { 55   {
56   T& t_; 56   T& t_;
57   57  
58   public: 58   public:
59   /** Constructor 59   /** Constructor
60   60  
61   Construct the wrapper from `t`. 61   Construct the wrapper from `t`.
62   62  
63   @param t The pilferable object. Ownership 63   @param t The pilferable object. Ownership
64   is not transferred. 64   is not transferred.
65   */ 65   */
66   explicit 66   explicit
67   constexpr 67   constexpr
HITCBC 68   2174109 pilfered(T&& t) noexcept 68   2174109 pilfered(T&& t) noexcept
HITCBC 69   2174109 : t_(t) 69   2174109 : t_(t)
70   { 70   {
HITCBC 71   2174109 } 71   2174109 }
72   72  
73   /** Return a reference to the pilferable object. 73   /** Return a reference to the pilferable object.
74   74  
75   This returns a reference to the wrapped object. 75   This returns a reference to the wrapped object.
76   */ 76   */
77   constexpr T& 77   constexpr T&
HITCBC 78   4316789 get() const noexcept 78   4316789 get() const noexcept
79   { 79   {
HITCBC 80   4316789 return t_; 80   4316789 return t_;
81   } 81   }
82   82  
83   /** Return a pointer to the pilferable object. 83   /** Return a pointer to the pilferable object.
84   84  
85   This returns a pointer to the wrapped object. 85   This returns a pointer to the wrapped object.
86   */ 86   */
87   constexpr T* 87   constexpr T*
88   operator->() const noexcept 88   operator->() const noexcept
89   { 89   {
90   //return std::addressof(t_); 90   //return std::addressof(t_);
91   return reinterpret_cast<T*>( 91   return reinterpret_cast<T*>(
92   const_cast<char *>( 92   const_cast<char *>(
93   &reinterpret_cast< 93   &reinterpret_cast<
94   const volatile char &>(t_))); 94   const volatile char &>(t_)));
95   } 95   }
96   }; 96   };
97   97  
98   #ifndef BOOST_JSON_DOCS 98   #ifndef BOOST_JSON_DOCS
99   // VFALCO Renamed this to work around an msvc bug 99   // VFALCO Renamed this to work around an msvc bug
100   namespace detail_pilfer { 100   namespace detail_pilfer {
101   template<class> 101   template<class>
102   struct not_pilfered 102   struct not_pilfered
103   { 103   {
104   }; 104   };
105   } // detail_pilfer 105   } // detail_pilfer
106   #endif 106   #endif
107   107  
108   /** Metafunction returning `true` if `T` is <em>PilferConstructible</em> 108   /** Metafunction returning `true` if `T` is <em>PilferConstructible</em>
109   109  
110   If `T` can be pilfer constructed, this metafunction is 110   If `T` can be pilfer constructed, this metafunction is
111   equal to `std::true_type`. Otherwise it is equal to 111   equal to `std::true_type`. Otherwise it is equal to
112   `std::false_type`. 112   `std::false_type`.
113   113  
114   @see @ref pilfer, @ref pilfered, 114   @see @ref pilfer, @ref pilfered,
115   <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0308r0.html"> 115   <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0308r0.html">
116   Valueless Variants Considered Harmful</a> 116   Valueless Variants Considered Harmful</a>
117   */ 117   */
118   template<class T> 118   template<class T>
119   struct is_pilfer_constructible 119   struct is_pilfer_constructible
120   #ifndef BOOST_JSON_DOCS 120   #ifndef BOOST_JSON_DOCS
121   : std::integral_constant<bool, 121   : std::integral_constant<bool,
122   std::is_nothrow_move_constructible<T>::value || 122   std::is_nothrow_move_constructible<T>::value ||
123   ( 123   (
124   std::is_nothrow_constructible< 124   std::is_nothrow_constructible<
125   T, pilfered<T> >::value && 125   T, pilfered<T> >::value &&
126   ! std::is_nothrow_constructible< 126   ! std::is_nothrow_constructible<
127   T, detail_pilfer::not_pilfered<T> >::value 127   T, detail_pilfer::not_pilfered<T> >::value
128   )> 128   )>
129   #endif 129   #endif
130   { 130   {
131   }; 131   };
132   132  
133   /** Indicate that an object `t` may be pilfered from. 133   /** Indicate that an object `t` may be pilfered from.
134   134  
135   A <em>pilfer</em> operation is the construction 135   A <em>pilfer</em> operation is the construction
136   of a new object of type `T` from an existing 136   of a new object of type `T` from an existing
137   object `t`. After the construction, the only 137   object `t`. After the construction, the only
138   valid operation on the pilfered-from object is 138   valid operation on the pilfered-from object is
139   destruction. This permits optimizations beyond 139   destruction. This permits optimizations beyond
140   those available for a move-construction, as the 140   those available for a move-construction, as the
141   pilfered-from object is not required to be in 141   pilfered-from object is not required to be in
142   a "usable" state. 142   a "usable" state.
143   \n 143   \n
144   This is used similarly to `std::move`. 144   This is used similarly to `std::move`.
145   145  
146   @par Example 146   @par Example
147   147  
148   A pilfer constructor accepts a single argument 148   A pilfer constructor accepts a single argument
149   of type @ref pilfered and throws nothing: 149   of type @ref pilfered and throws nothing:
150   150  
151   @code 151   @code
152   struct T 152   struct T
153   { 153   {
154   T( pilfered<T> ) noexcept; 154   T( pilfered<T> ) noexcept;
155   }; 155   };
156   @endcode 156   @endcode
157   157  
158   Pilfer construction is performed using @ref pilfer : 158   Pilfer construction is performed using @ref pilfer :
159   159  
160   @code 160   @code
161   { 161   {
162   T t1; // default construction 162   T t1; // default construction
163   T t2( pilfer( t1 ) ); // pilfer-construct from t1 163   T t2( pilfer( t1 ) ); // pilfer-construct from t1
164   164  
165   // At this point, t1 may only be destroyed 165   // At this point, t1 may only be destroyed
166   } 166   }
167   @endcode 167   @endcode
168   168  
169   @see @ref pilfered, @ref is_pilfer_constructible, 169   @see @ref pilfered, @ref is_pilfer_constructible,
170   <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0308r0.html"> 170   <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0308r0.html">
171   Valueless Variants Considered Harmful</a> 171   Valueless Variants Considered Harmful</a>
172   */ 172   */
173   template<class T> 173   template<class T>
174   auto 174   auto
HITCBC 175   6327237 pilfer(T&& t) noexcept -> 175   6327237 pilfer(T&& t) noexcept ->
176   typename std::conditional< 176   typename std::conditional<
177   std::is_nothrow_constructible< 177   std::is_nothrow_constructible<
178   typename std::remove_reference<T>::type, 178   typename std::remove_reference<T>::type,
179   pilfered<typename 179   pilfered<typename
180   std::remove_reference<T>::type> >::value && 180   std::remove_reference<T>::type> >::value &&
181   ! std::is_nothrow_constructible< 181   ! std::is_nothrow_constructible<
182   typename std::remove_reference<T>::type, 182   typename std::remove_reference<T>::type,
183   detail_pilfer::not_pilfered<typename 183   detail_pilfer::not_pilfered<typename
184   std::remove_reference<T>::type> >::value, 184   std::remove_reference<T>::type> >::value,
185   pilfered<typename std::remove_reference<T>::type>, 185   pilfered<typename std::remove_reference<T>::type>,
186   typename std::remove_reference<T>::type&& 186   typename std::remove_reference<T>::type&&
187   >::type 187   >::type
188   { 188   {
189   using U = 189   using U =
190   typename std::remove_reference<T>::type; 190   typename std::remove_reference<T>::type;
191   BOOST_CORE_STATIC_ASSERT( is_pilfer_constructible<U>::value ); 191   BOOST_CORE_STATIC_ASSERT( is_pilfer_constructible<U>::value );
192   return typename std::conditional< 192   return typename std::conditional<
193   std::is_nothrow_constructible< 193   std::is_nothrow_constructible<
194   U, pilfered<U> >::value && 194   U, pilfered<U> >::value &&
195   ! std::is_nothrow_constructible< 195   ! std::is_nothrow_constructible<
196   U, detail_pilfer::not_pilfered<U> >::value, 196   U, detail_pilfer::not_pilfered<U> >::value,
197   pilfered<U>, U&& 197   pilfered<U>, U&&
HITCBC 198   6327237 >::type(std::move(t)); 198   6327237 >::type(std::move(t));
199   } 199   }
200   200  
201   /* 201   /*
202   template<class T> 202   template<class T>
203   void 203   void
204   relocate(T* dest, T& src) noexcept 204   relocate(T* dest, T& src) noexcept
205   { 205   {
206   BOOST_CORE_STATIC_ASSERT( is_pilfer_constructible<T>::value ); 206   BOOST_CORE_STATIC_ASSERT( is_pilfer_constructible<T>::value );
207   ::new(dest) T(pilfer(src)); 207   ::new(dest) T(pilfer(src));
208   src.~T(); 208   src.~T();
209   } 209   }
210   */ 210   */
211   211  
212   } // json 212   } // json
213   } // boost 213   } // boost
214   214  
215   215  
216   #endif 216   #endif