// // Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com) // // 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) // // Official repository: https://github.com/boostorg/json // #ifndef BOOST_JSON_PILFER_HPP #define BOOST_JSON_PILFER_HPP #include #include #include /* Implements "pilfering" from P0308R0 @see http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0308r0.html */ namespace boost { namespace json { /** Tag wrapper to specify pilfer-construction. This wrapper is used to specify a pilfer constructor overload. @par Example A pilfer constructor accepts a single argument of type @ref pilfered and throws nothing: @code struct T { T( pilfered ) noexcept; }; @endcode @note The constructor should not be marked explicit. @see @ref pilfer, @ref is_pilfer_constructible, Valueless Variants Considered Harmful */ template class pilfered { T& t_; public: /** Constructor Construct the wrapper from `t`. @param t The pilferable object. Ownership is not transferred. */ explicit constexpr pilfered(T&& t) noexcept : t_(t) { } /** Return a reference to the pilferable object. This returns a reference to the wrapped object. */ constexpr T& get() const noexcept { return t_; } /** Return a pointer to the pilferable object. This returns a pointer to the wrapped object. */ constexpr T* operator->() const noexcept { //return std::addressof(t_); return reinterpret_cast( const_cast( &reinterpret_cast< const volatile char &>(t_))); } }; #ifndef BOOST_JSON_DOCS // VFALCO Renamed this to work around an msvc bug namespace detail_pilfer { template struct not_pilfered { }; } // detail_pilfer #endif /** Metafunction returning `true` if `T` is PilferConstructible If `T` can be pilfer constructed, this metafunction is equal to `std::true_type`. Otherwise it is equal to `std::false_type`. @see @ref pilfer, @ref pilfered, Valueless Variants Considered Harmful */ template struct is_pilfer_constructible #ifndef BOOST_JSON_DOCS : std::integral_constant::value || ( std::is_nothrow_constructible< T, pilfered >::value && ! std::is_nothrow_constructible< T, detail_pilfer::not_pilfered >::value )> #endif { }; /** Indicate that an object `t` may be pilfered from. A pilfer operation is the construction of a new object of type `T` from an existing object `t`. After the construction, the only valid operation on the pilfered-from object is destruction. This permits optimizations beyond those available for a move-construction, as the pilfered-from object is not required to be in a "usable" state. \n This is used similarly to `std::move`. @par Example A pilfer constructor accepts a single argument of type @ref pilfered and throws nothing: @code struct T { T( pilfered ) noexcept; }; @endcode Pilfer construction is performed using @ref pilfer : @code { T t1; // default construction T t2( pilfer( t1 ) ); // pilfer-construct from t1 // At this point, t1 may only be destroyed } @endcode @see @ref pilfered, @ref is_pilfer_constructible, Valueless Variants Considered Harmful */ template auto pilfer(T&& t) noexcept -> typename std::conditional< std::is_nothrow_constructible< typename std::remove_reference::type, pilfered::type> >::value && ! std::is_nothrow_constructible< typename std::remove_reference::type, detail_pilfer::not_pilfered::type> >::value, pilfered::type>, typename std::remove_reference::type&& >::type { using U = typename std::remove_reference::type; static_assert( is_pilfer_constructible::value, ""); return typename std::conditional< std::is_nothrow_constructible< U, pilfered >::value && ! std::is_nothrow_constructible< U, detail_pilfer::not_pilfered >::value, pilfered, U&& >::type(std::move(t)); } /* template void relocate(T* dest, T& src) noexcept { static_assert( is_pilfer_constructible::value, ""); ::new(dest) T(pilfer(src)); src.~T(); } */ } // json } // boost #endif