1 /*! 2 @file 3 Defines `boost::hana::pair`. 4 5 @copyright Louis Dionne 2013-2017 6 Distributed under the Boost Software License, Version 1.0. 7 (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) 8 */ 9 10 #ifndef BOOST_HANA_PAIR_HPP 11 #define BOOST_HANA_PAIR_HPP 12 13 #include <boost/hana/fwd/pair.hpp> 14 15 #include <boost/hana/config.hpp> 16 #include <boost/hana/detail/decay.hpp> 17 #include <boost/hana/detail/ebo.hpp> 18 #include <boost/hana/detail/intrinsics.hpp> 19 #include <boost/hana/detail/operators/adl.hpp> 20 #include <boost/hana/detail/operators/comparable.hpp> 21 #include <boost/hana/detail/operators/orderable.hpp> 22 #include <boost/hana/fwd/core/make.hpp> 23 #include <boost/hana/fwd/first.hpp> 24 #include <boost/hana/fwd/second.hpp> 25 26 #include <type_traits> 27 #include <utility> 28 29 30 BOOST_HANA_NAMESPACE_BEGIN 31 namespace detail { 32 template <int> struct pix; // pair index 33 } 34 35 ////////////////////////////////////////////////////////////////////////// 36 // pair 37 ////////////////////////////////////////////////////////////////////////// 38 //! @cond 39 template <typename First, typename Second> 40 #ifdef BOOST_HANA_WORKAROUND_MSVC_EMPTYBASE 41 struct __declspec(empty_bases) pair : detail::operators::adl<pair<First, Second>> 42 #else 43 struct pair : detail::operators::adl<pair<First, Second>> 44 #endif 45 , private detail::ebo<detail::pix<0>, First> 46 , private detail::ebo<detail::pix<1>, Second> 47 { 48 // Default constructor 49 template <typename ...dummy, typename = typename std::enable_if< 50 BOOST_HANA_TT_IS_CONSTRUCTIBLE(First, dummy...) && 51 BOOST_HANA_TT_IS_CONSTRUCTIBLE(Second, dummy...) 52 >::type> 53 constexpr pair() 54 : detail::ebo<detail::pix<0>, First>() 55 , detail::ebo<detail::pix<1>, Second>() 56 { } 57 58 // Variadic constructors 59 template <typename ...dummy, typename = typename std::enable_if< 60 BOOST_HANA_TT_IS_CONSTRUCTIBLE(First, First const&, dummy...) && 61 BOOST_HANA_TT_IS_CONSTRUCTIBLE(Second, Second const&, dummy...) 62 >::type> 63 constexpr pair(First const& fst, Second const& snd) 64 : detail::ebo<detail::pix<0>, First>(fst) 65 , detail::ebo<detail::pix<1>, Second>(snd) 66 { } 67 68 template <typename T, typename U, typename = typename std::enable_if< 69 BOOST_HANA_TT_IS_CONVERTIBLE(T&&, First) && 70 BOOST_HANA_TT_IS_CONVERTIBLE(U&&, Second) 71 >::type> 72 constexpr pair(T&& t, U&& u) 73 : detail::ebo<detail::pix<0>, First>(static_cast<T&&>(t)) 74 , detail::ebo<detail::pix<1>, Second>(static_cast<U&&>(u)) 75 { } 76 77 78 // Possibly converting copy and move constructors 79 template <typename T, typename U, typename = typename std::enable_if< 80 BOOST_HANA_TT_IS_CONSTRUCTIBLE(First, T const&) && 81 BOOST_HANA_TT_IS_CONSTRUCTIBLE(Second, U const&) && 82 BOOST_HANA_TT_IS_CONVERTIBLE(T const&, First) && 83 BOOST_HANA_TT_IS_CONVERTIBLE(U const&, Second) 84 >::type> 85 constexpr pair(pair<T, U> const& other) 86 : detail::ebo<detail::pix<0>, First>(hana::first(other)) 87 , detail::ebo<detail::pix<1>, Second>(hana::second(other)) 88 { } 89 90 template <typename T, typename U, typename = typename std::enable_if< 91 BOOST_HANA_TT_IS_CONSTRUCTIBLE(First, T&&) && 92 BOOST_HANA_TT_IS_CONSTRUCTIBLE(Second, U&&) && 93 BOOST_HANA_TT_IS_CONVERTIBLE(T&&, First) && 94 BOOST_HANA_TT_IS_CONVERTIBLE(U&&, Second) 95 >::type> 96 constexpr pair(pair<T, U>&& other) 97 : detail::ebo<detail::pix<0>, First>(hana::first(static_cast<pair<T, U>&&>(other))) 98 , detail::ebo<detail::pix<1>, Second>(hana::second(static_cast<pair<T, U>&&>(other))) 99 { } 100 101 102 // Copy and move assignment 103 template <typename T, typename U, typename = typename std::enable_if< 104 BOOST_HANA_TT_IS_ASSIGNABLE(First&, T const&) && 105 BOOST_HANA_TT_IS_ASSIGNABLE(Second&, U const&) 106 >::type> 107 constexpr pair& operator=(pair<T, U> const& other) { 108 hana::first(*this) = hana::first(other); 109 hana::second(*this) = hana::second(other); 110 return *this; 111 } 112 113 template <typename T, typename U, typename = typename std::enable_if< 114 BOOST_HANA_TT_IS_ASSIGNABLE(First&, T&&) && 115 BOOST_HANA_TT_IS_ASSIGNABLE(Second&, U&&) 116 >::type> 117 constexpr pair& operator=(pair<T, U>&& other) { 118 hana::first(*this) = hana::first(static_cast<pair<T, U>&&>(other)); 119 hana::second(*this) = hana::second(static_cast<pair<T, U>&&>(other)); 120 return *this; 121 } 122 123 // Prevent the compiler from defining the default copy and move 124 // constructors, which interfere with the SFINAE above. 125 ~pair() = default; 126 127 friend struct first_impl<pair_tag>; 128 friend struct second_impl<pair_tag>; 129 template <typename F, typename S> friend struct pair; 130 }; 131 //! @endcond 132 133 template <typename First, typename Second> 134 struct tag_of<pair<First, Second>> { 135 using type = pair_tag; 136 }; 137 138 ////////////////////////////////////////////////////////////////////////// 139 // Operators 140 ////////////////////////////////////////////////////////////////////////// 141 namespace detail { 142 template <> 143 struct comparable_operators<pair_tag> { 144 static constexpr bool value = true; 145 }; 146 template <> 147 struct orderable_operators<pair_tag> { 148 static constexpr bool value = true; 149 }; 150 } 151 152 ////////////////////////////////////////////////////////////////////////// 153 // Product 154 ////////////////////////////////////////////////////////////////////////// 155 template <> 156 struct make_impl<pair_tag> { 157 template <typename F, typename S> 158 static constexpr pair< 159 typename detail::decay<F>::type, 160 typename detail::decay<S>::type 161 > apply(F&& f, S&& s) { 162 return {static_cast<F&&>(f), static_cast<S&&>(s)}; 163 } 164 }; 165 166 template <> 167 struct first_impl<pair_tag> { 168 template <typename First, typename Second> 169 static constexpr decltype(auto) apply(hana::pair<First, Second>& p) { 170 return detail::ebo_get<detail::pix<0>>( 171 static_cast<detail::ebo<detail::pix<0>, First>&>(p) 172 ); 173 } 174 template <typename First, typename Second> 175 static constexpr decltype(auto) apply(hana::pair<First, Second> const& p) { 176 return detail::ebo_get<detail::pix<0>>( 177 static_cast<detail::ebo<detail::pix<0>, First> const&>(p) 178 ); 179 } 180 template <typename First, typename Second> 181 static constexpr decltype(auto) apply(hana::pair<First, Second>&& p) { 182 return detail::ebo_get<detail::pix<0>>( 183 static_cast<detail::ebo<detail::pix<0>, First>&&>(p) 184 ); 185 } 186 }; 187 188 template <> 189 struct second_impl<pair_tag> { 190 template <typename First, typename Second> 191 static constexpr decltype(auto) apply(hana::pair<First, Second>& p) { 192 return detail::ebo_get<detail::pix<1>>( 193 static_cast<detail::ebo<detail::pix<1>, Second>&>(p) 194 ); 195 } 196 template <typename First, typename Second> 197 static constexpr decltype(auto) apply(hana::pair<First, Second> const& p) { 198 return detail::ebo_get<detail::pix<1>>( 199 static_cast<detail::ebo<detail::pix<1>, Second> const&>(p) 200 ); 201 } 202 template <typename First, typename Second> 203 static constexpr decltype(auto) apply(hana::pair<First, Second>&& p) { 204 return detail::ebo_get<detail::pix<1>>( 205 static_cast<detail::ebo<detail::pix<1>, Second>&&>(p) 206 ); 207 } 208 }; 209 BOOST_HANA_NAMESPACE_END 210 211 #endif // !BOOST_HANA_PAIR_HPP 212