// // Copyright (c) 2018-2019 Vinnie Falco (vinnie dot falco at gmail dot 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/vinniefalco/json // #ifndef BOOST_PILFER_HPP #define BOOST_PILFER_HPP #include #include #include /* Implements "pilfering" from P0308R0 "Valueless Variants Considered Harmful" http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0308r0.html Author: Peter Dimov */ namespace boost { template class pilfered { T& t_; public: explicit constexpr pilfered(T&& t) noexcept : t_(t) { } constexpr T& get() const noexcept { return t_; } constexpr T* operator->() const noexcept { return std::addressof(t_); } }; namespace detail { template struct not_pilfered { }; } // detail template struct is_pilfer_constructible : std::integral_constant::value || ( std::is_nothrow_constructible< T, pilfered >::value && ! std::is_nothrow_constructible< T, detail::not_pilfered >::value )> { }; 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::not_pilfered::type> >::value, pilfered::type>, typename std::remove_reference::type&& >::type { using U = typename std::remove_reference::type; BOOST_JSON_STATIC_ASSERT( is_pilfer_constructible::value); return typename std::conditional< std::is_nothrow_constructible< U, pilfered >::value && ! std::is_nothrow_constructible< U, detail::not_pilfered >::value, pilfered, U&& >::type(std::move(t)); } template void relocate(T* dest, T& src) noexcept { BOOST_JSON_STATIC_ASSERT( is_pilfer_constructible::value); ::new(dest) T(pilfer(src)); src.~T(); } } // boost #endif