Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-12-16 09:54:04

0001 //
0002 // Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com)
0003 //
0004 // Distributed under the Boost Software License, Version 1.0. (See accompanying
0005 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0006 //
0007 // Official repository: https://github.com/boostorg/json
0008 //
0009 
0010 #ifndef BOOST_JSON_PILFER_HPP
0011 #define BOOST_JSON_PILFER_HPP
0012 
0013 #include <boost/json/detail/config.hpp>
0014 #include <type_traits>
0015 #include <utility>
0016 
0017 /*
0018     Implements "pilfering" from P0308R0
0019 
0020     @see
0021         http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0308r0.html
0022 */
0023 
0024 namespace boost {
0025 namespace json {
0026 
0027 /** Tag wrapper to specify pilfer-construction.
0028 
0029     This wrapper is used to specify a pilfer constructor
0030     overload.
0031 
0032     @par Example
0033 
0034     A pilfer constructor accepts a single argument
0035     of type @ref pilfered and throws nothing:
0036 
0037     @code
0038     struct T
0039     {
0040         T( pilfered<T> ) noexcept;
0041     };
0042     @endcode
0043 
0044     @note
0045 
0046     The constructor should not be marked explicit.
0047 
0048     @see @ref pilfer, @ref is_pilfer_constructible,
0049     <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0308r0.html">
0050         Valueless Variants Considered Harmful</a>
0051 */
0052 template<class T>
0053 class pilfered
0054 {
0055     T& t_;
0056 
0057 public:
0058     /** Constructor
0059 
0060         Construct the wrapper from `t`.
0061 
0062         @param t The pilferable object. Ownership
0063         is not transferred.
0064     */
0065     explicit
0066     constexpr
0067     pilfered(T&& t) noexcept
0068         : t_(t)
0069     {
0070     }
0071 
0072     /** Return a reference to the pilferable object.
0073 
0074         This returns a reference to the wrapped object.
0075     */
0076     constexpr T&
0077     get() const noexcept
0078     {
0079         return t_;
0080     }
0081 
0082     /** Return a pointer to the pilferable object.
0083 
0084         This returns a pointer to the wrapped object.
0085     */
0086     constexpr T*
0087     operator->() const noexcept
0088     {
0089         //return std::addressof(t_);
0090         return reinterpret_cast<T*>(
0091             const_cast<char *>(
0092                 &reinterpret_cast<
0093                     const volatile char &>(t_)));
0094     }
0095 };
0096 
0097 #ifndef BOOST_JSON_DOCS
0098 // VFALCO Renamed this to work around an msvc bug
0099 namespace detail_pilfer {
0100 template<class>
0101 struct not_pilfered
0102 {
0103 };
0104 } // detail_pilfer
0105 #endif
0106 
0107 /** Metafunction returning `true` if `T` is <em>PilferConstructible</em>
0108 
0109     If `T` can be pilfer constructed, this metafunction is
0110     equal to `std::true_type`. Otherwise it is equal to
0111     `std::false_type`.
0112 
0113     @see @ref pilfer, @ref pilfered,
0114     <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0308r0.html">
0115         Valueless Variants Considered Harmful</a>
0116 */
0117 template<class T>
0118 struct is_pilfer_constructible
0119 #ifndef BOOST_JSON_DOCS
0120     : std::integral_constant<bool,
0121         std::is_nothrow_move_constructible<T>::value ||
0122         (
0123             std::is_nothrow_constructible<
0124                 T, pilfered<T> >::value &&
0125             ! std::is_nothrow_constructible<
0126                 T, detail_pilfer::not_pilfered<T> >::value
0127         )>
0128 #endif
0129 {
0130 };
0131 
0132 /** Indicate that an object `t` may be pilfered from.
0133 
0134     A <em>pilfer</em> operation is the construction
0135     of a new object of type `T` from an existing
0136     object `t`. After the construction, the only
0137     valid operation on the pilfered-from object is
0138     destruction. This permits optimizations beyond
0139     those available for a move-construction, as the
0140     pilfered-from object is not required to be in
0141     a "usable" state.
0142 \n
0143     This is used similarly to `std::move`.
0144 
0145     @par Example
0146 
0147     A pilfer constructor accepts a single argument
0148     of type @ref pilfered and throws nothing:
0149 
0150     @code
0151     struct T
0152     {
0153         T( pilfered<T> ) noexcept;
0154     };
0155     @endcode
0156 
0157     Pilfer construction is performed using @ref pilfer :
0158 
0159     @code
0160     {
0161         T t1;                       // default construction
0162         T t2( pilfer( t1 ) );       // pilfer-construct from t1
0163 
0164         // At this point, t1 may only be destroyed
0165     }
0166     @endcode
0167 
0168     @see @ref pilfered, @ref is_pilfer_constructible,
0169     <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0308r0.html">
0170         Valueless Variants Considered Harmful</a>
0171 */
0172 template<class T>
0173 auto
0174 pilfer(T&& t) noexcept ->
0175     typename std::conditional<
0176         std::is_nothrow_constructible<
0177             typename std::remove_reference<T>::type,
0178             pilfered<typename
0179                 std::remove_reference<T>::type> >::value &&
0180         ! std::is_nothrow_constructible<
0181             typename std::remove_reference<T>::type,
0182             detail_pilfer::not_pilfered<typename
0183                 std::remove_reference<T>::type> >::value,
0184         pilfered<typename std::remove_reference<T>::type>,
0185         typename std::remove_reference<T>::type&&
0186             >::type
0187 {
0188     using U =
0189         typename std::remove_reference<T>::type;
0190     static_assert(
0191         is_pilfer_constructible<U>::value, "");
0192     return typename std::conditional<
0193         std::is_nothrow_constructible<
0194             U, pilfered<U> >::value &&
0195         ! std::is_nothrow_constructible<
0196             U, detail_pilfer::not_pilfered<U> >::value,
0197         pilfered<U>, U&&
0198             >::type(std::move(t));
0199 }
0200 
0201 /*
0202 template<class T>
0203 void
0204 relocate(T* dest, T& src) noexcept
0205 {
0206     static_assert(
0207         is_pilfer_constructible<T>::value, "");
0208     ::new(dest) T(pilfer(src));
0209     src.~T();
0210 }
0211 */
0212 
0213 } // json
0214 } // boost
0215 
0216 
0217 #endif