//////////////////////////////////////////////////////////////////////////////// /// \file utility.hpp /// /// \brief This header provides definitions from the C++ header //////////////////////////////////////////////////////////////////////////////// /* The MIT License (MIT) Copyright (c) 2020 Matthew Rodusek All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef BPSTD_UTILITY_HPP #define BPSTD_UTILITY_HPP #if defined(_MSC_VER) && (_MSC_VER >= 1200) # pragma once #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) #include "detail/config.hpp" #include "detail/move.hpp" // IWYU pragma: export #include "type_traits.hpp" // add_const_t #include // to proxy the API #include // std::size_t BPSTD_COMPILER_DIAGNOSTIC_PREAMBLE namespace bpstd { //============================================================================ // struct : in_place_t //============================================================================ /// \brief This function is a special disambiguation tag for variadic /// functions, used in any and optional /// /// \note Calling this function results in undefined behaviour. struct in_place_t { explicit in_place_t() = default; }; BPSTD_CPP17_INLINE constexpr in_place_t in_place{}; //============================================================================ // in_place_type_t //============================================================================ /// \brief This function is a special disambiguation tag for variadic /// functions, used in any and optional /// /// \note Calling this function results in undefined behaviour. template struct in_place_type_t { explicit in_place_type_t() = default; }; #if BPSTD_HAS_TEMPLATE_VARIABLES template BPSTD_CPP17_INLINE constexpr in_place_type_t in_place_type{}; #endif //============================================================================ // in_place_index_t //============================================================================ /// \brief This function is a special disambiguation tag for variadic /// functions, used in any and optional /// /// \note Calling this function results in undefined behaviour. template struct in_place_index_t { explicit in_place_index_t() = default; }; #if BPSTD_HAS_TEMPLATE_VARIABLES template BPSTD_CPP17_INLINE constexpr in_place_index_t in_place_index{}; #endif //============================================================================ // non-member functions //============================================================================ //---------------------------------------------------------------------------- // Utilities //---------------------------------------------------------------------------- /// \brief Moves a type \p x if it move-construction is non-throwing /// /// \param x the parameter to move /// \return an rvalue reference if nothrow moveable, const reference otherwise template constexpr auto move_if_noexcept(T &x) noexcept -> typename bpstd::conditional< !bpstd::is_nothrow_move_constructible::value && bpstd::is_copy_constructible::value, const T &, T &&>::type; /// \brief Forms an lvalue reference to const type of t /// /// \param t the type to form an lvalue reference to /// \return the reference to const T template constexpr auto as_const(T &t) noexcept -> add_const_t &; template void as_const(const T&&) = delete; /// \brief Replaces the value of obj with new_value and returns the old value /// of obj. /// /// \pre \p T must meet the requirements of MoveConstructible. /// /// \pre It must be possible to move-assign objects of type \p U to objects of /// type \p T /// /// \param obj object whose value to replace /// \param new_value the value to assign to obj template BPSTD_CPP14_CONSTEXPR auto exchange(T &obj, U &&new_value) -> T; //============================================================================ // class : pair //============================================================================ template using pair = std::pair; //============================================================================ // non-member functions : class : pair //============================================================================ //---------------------------------------------------------------------------- // Utilities //---------------------------------------------------------------------------- // C++11 does not implement const pair&& template constexpr auto get(pair &p) noexcept -> conditional_t &; template constexpr auto get(pair &&p) noexcept -> conditional_t &&; template constexpr auto get(const pair &p) noexcept -> const conditional_t &; template constexpr auto get(const pair &&p) noexcept -> const conditional_t &&; template constexpr auto get(pair &p) noexcept -> T &; template constexpr auto get(pair &&p) noexcept -> T &&; template constexpr auto get(const pair &p) noexcept -> const T &; template constexpr auto get(const pair &&p) noexcept -> const T &&; template constexpr auto get(pair &p) noexcept -> T &; template constexpr auto get(const pair &p) noexcept -> const T &; template constexpr auto get(pair &&p) noexcept -> T &&; template constexpr auto get(const pair &&p) noexcept -> const T &&; //============================================================================ // struct : integer_sequence //============================================================================ template struct integer_sequence { using value_type = T; static constexpr auto size() noexcept -> std::size_t { return sizeof...(Ints); } }; template using index_sequence = integer_sequence; namespace detail { template struct make_integer_sequence_impl : make_integer_sequence_impl{}; template struct make_integer_sequence_impl : type_identity>{}; } // namespace detail template using make_integer_sequence = typename detail::make_integer_sequence_impl::type; template using make_index_sequence = make_integer_sequence; template using index_sequence_for = make_index_sequence; } // namespace bpstd //============================================================================== // non-member functions //============================================================================== //------------------------------------------------------------------------------ // Utilities //------------------------------------------------------------------------------ template inline BPSTD_INLINE_VISIBILITY constexpr auto bpstd::move_if_noexcept(T &x) noexcept -> typename bpstd::conditional< !bpstd::is_nothrow_move_constructible::value && bpstd::is_copy_constructible::value, const T &, T &&>::type { using result_type = conditional_t< !is_nothrow_move_constructible::value && is_copy_constructible::value, const T&, T&& >; return static_cast(x); } template inline BPSTD_INLINE_VISIBILITY constexpr auto bpstd::as_const(T &t) noexcept -> bpstd::add_const_t & { return t; } template inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR auto bpstd::exchange(T &obj, U &&new_value) -> T { auto old_value = bpstd::move(obj); obj = bpstd::forward(new_value); return old_value; } //============================================================================== // definitions : non-member functions : class : pair //============================================================================== //------------------------------------------------------------------------------ // Utilities //------------------------------------------------------------------------------ template inline BPSTD_INLINE_VISIBILITY constexpr auto bpstd::get(pair &p) noexcept -> bpstd::conditional_t & { static_assert(N<=1, "N must be either 0 or 1 for get(pair)"); return std::get(p); } template inline BPSTD_INLINE_VISIBILITY constexpr auto bpstd::get(pair &&p) noexcept -> bpstd::conditional_t && { static_assert(N<=1, "N must be either 0 or 1 for get(pair)"); return move(std::get(p)); } template inline BPSTD_INLINE_VISIBILITY constexpr auto bpstd::get(const pair &p) noexcept -> const bpstd::conditional_t & { static_assert(N<=1, "N must be either 0 or 1 for get(pair)"); return std::get(p); } template inline BPSTD_INLINE_VISIBILITY constexpr auto bpstd::get(const pair &&p) noexcept -> const bpstd::conditional_t && { static_assert(N<=1, "N must be either 0 or 1 for get(pair)"); return move(std::get(p)); } template inline BPSTD_INLINE_VISIBILITY constexpr auto bpstd::get(pair &p) noexcept -> T & { return p.first; } template inline BPSTD_INLINE_VISIBILITY constexpr auto bpstd::get(const pair &p) noexcept -> const T & { return p.first; } template inline BPSTD_INLINE_VISIBILITY constexpr auto bpstd::get(pair &&p) noexcept -> T && { return move(p.first); } template inline BPSTD_INLINE_VISIBILITY constexpr auto bpstd::get(const pair &&p) noexcept -> const T && { return move(p.first); } template inline BPSTD_INLINE_VISIBILITY constexpr auto bpstd::get(pair &p) noexcept -> T & { return p.second; } template inline BPSTD_INLINE_VISIBILITY constexpr auto bpstd::get(const pair &p) noexcept -> const T & { return p.second; } template inline BPSTD_INLINE_VISIBILITY constexpr auto bpstd::get(pair &&p) noexcept -> T && { return move(p.second); } template inline BPSTD_INLINE_VISIBILITY constexpr auto bpstd::get(const pair &&p) noexcept -> const T && { return move(p.second); } BPSTD_COMPILER_DIAGNOSTIC_POSTAMBLE #endif /* BPSTD_UTILITY_HPP */