123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217 |
- //
- // Copyright (c) 2019 Vinnie Falco ([email protected])
- //
- // 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 <boost/json/detail/config.hpp>
- #include <type_traits>
- #include <utility>
- /*
- 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<T> ) noexcept;
- };
- @endcode
- @note
- The constructor should not be marked explicit.
- @see @ref pilfer, @ref is_pilfer_constructible,
- <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0308r0.html">
- Valueless Variants Considered Harmful</a>
- */
- template<class T>
- 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<T*>(
- const_cast<char *>(
- &reinterpret_cast<
- const volatile char &>(t_)));
- }
- };
- #ifndef BOOST_JSON_DOCS
- // VFALCO Renamed this to work around an msvc bug
- namespace detail_pilfer {
- template<class>
- struct not_pilfered
- {
- };
- } // detail_pilfer
- #endif
- /** Metafunction returning `true` if `T` is <em>PilferConstructible</em>
- 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,
- <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0308r0.html">
- Valueless Variants Considered Harmful</a>
- */
- template<class T>
- struct is_pilfer_constructible
- #ifndef BOOST_JSON_DOCS
- : std::integral_constant<bool,
- std::is_nothrow_move_constructible<T>::value ||
- (
- std::is_nothrow_constructible<
- T, pilfered<T> >::value &&
- ! std::is_nothrow_constructible<
- T, detail_pilfer::not_pilfered<T> >::value
- )>
- #endif
- {
- };
- /** Indicate that an object `t` may be pilfered from.
- A <em>pilfer</em> 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<T> ) 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,
- <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0308r0.html">
- Valueless Variants Considered Harmful</a>
- */
- template<class T>
- auto
- pilfer(T&& t) noexcept ->
- typename std::conditional<
- std::is_nothrow_constructible<
- typename std::remove_reference<T>::type,
- pilfered<typename
- std::remove_reference<T>::type> >::value &&
- ! std::is_nothrow_constructible<
- typename std::remove_reference<T>::type,
- detail_pilfer::not_pilfered<typename
- std::remove_reference<T>::type> >::value,
- pilfered<typename std::remove_reference<T>::type>,
- typename std::remove_reference<T>::type&&
- >::type
- {
- using U =
- typename std::remove_reference<T>::type;
- static_assert(
- is_pilfer_constructible<U>::value, "");
- return typename std::conditional<
- std::is_nothrow_constructible<
- U, pilfered<U> >::value &&
- ! std::is_nothrow_constructible<
- U, detail_pilfer::not_pilfered<U> >::value,
- pilfered<U>, U&&
- >::type(std::move(t));
- }
- /*
- template<class T>
- void
- relocate(T* dest, T& src) noexcept
- {
- static_assert(
- is_pilfer_constructible<T>::value, "");
- ::new(dest) T(pilfer(src));
- src.~T();
- }
- */
- } // json
- } // boost
- #endif
|