/*! @file Defines `boost::hana::pair`. @copyright Louis Dionne 2013-2017 Distributed under the Boost Software License, Version 1.0. (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) */ #ifndef BOOST_HANA_PAIR_HPP #define BOOST_HANA_PAIR_HPP #include #include #include #include #include #include #include #include #include #include #include #include #include BOOST_HANA_NAMESPACE_BEGIN namespace detail { template struct pix; // pair index } ////////////////////////////////////////////////////////////////////////// // pair ////////////////////////////////////////////////////////////////////////// //! @cond template #ifdef BOOST_HANA_WORKAROUND_MSVC_EMPTYBASE struct __declspec(empty_bases) pair : detail::operators::adl> #else struct pair : detail::operators::adl> #endif , private detail::ebo, First> , private detail::ebo, Second> { // Default constructor template ::type> constexpr pair() : detail::ebo, First>() , detail::ebo, Second>() { } // Variadic constructors template ::type> constexpr pair(First const& fst, Second const& snd) : detail::ebo, First>(fst) , detail::ebo, Second>(snd) { } template ::type> constexpr pair(T&& t, U&& u) : detail::ebo, First>(static_cast(t)) , detail::ebo, Second>(static_cast(u)) { } // Possibly converting copy and move constructors template ::type> constexpr pair(pair const& other) : detail::ebo, First>(hana::first(other)) , detail::ebo, Second>(hana::second(other)) { } template ::type> constexpr pair(pair&& other) : detail::ebo, First>(hana::first(static_cast&&>(other))) , detail::ebo, Second>(hana::second(static_cast&&>(other))) { } // Copy and move assignment template ::type> constexpr pair& operator=(pair const& other) { hana::first(*this) = hana::first(other); hana::second(*this) = hana::second(other); return *this; } template ::type> constexpr pair& operator=(pair&& other) { hana::first(*this) = hana::first(static_cast&&>(other)); hana::second(*this) = hana::second(static_cast&&>(other)); return *this; } // Prevent the compiler from defining the default copy and move // constructors, which interfere with the SFINAE above. ~pair() = default; friend struct first_impl; friend struct second_impl; template friend struct pair; }; //! @endcond template struct tag_of> { using type = pair_tag; }; ////////////////////////////////////////////////////////////////////////// // Operators ////////////////////////////////////////////////////////////////////////// namespace detail { template <> struct comparable_operators { static constexpr bool value = true; }; template <> struct orderable_operators { static constexpr bool value = true; }; } ////////////////////////////////////////////////////////////////////////// // Product ////////////////////////////////////////////////////////////////////////// template <> struct make_impl { template static constexpr pair< typename detail::decay::type, typename detail::decay::type > apply(F&& f, S&& s) { return {static_cast(f), static_cast(s)}; } }; template <> struct first_impl { template static constexpr decltype(auto) apply(hana::pair& p) { return detail::ebo_get>( static_cast, First>&>(p) ); } template static constexpr decltype(auto) apply(hana::pair const& p) { return detail::ebo_get>( static_cast, First> const&>(p) ); } template static constexpr decltype(auto) apply(hana::pair&& p) { return detail::ebo_get>( static_cast, First>&&>(p) ); } }; template <> struct second_impl { template static constexpr decltype(auto) apply(hana::pair& p) { return detail::ebo_get>( static_cast, Second>&>(p) ); } template static constexpr decltype(auto) apply(hana::pair const& p) { return detail::ebo_get>( static_cast, Second> const&>(p) ); } template static constexpr decltype(auto) apply(hana::pair&& p) { return detail::ebo_get>( static_cast, Second>&&>(p) ); } }; BOOST_HANA_NAMESPACE_END #endif // !BOOST_HANA_PAIR_HPP