diff options
Diffstat (limited to 'boost/hana/pair.hpp')
-rw-r--r-- | boost/hana/pair.hpp | 106 |
1 files changed, 83 insertions, 23 deletions
diff --git a/boost/hana/pair.hpp b/boost/hana/pair.hpp index 5a4bf87e23..75cd9e287b 100644 --- a/boost/hana/pair.hpp +++ b/boost/hana/pair.hpp @@ -2,7 +2,7 @@ @file Defines `boost::hana::pair`. -@copyright Louis Dionne 2013-2016 +@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) */ @@ -12,9 +12,9 @@ Distributed under the Boost Software License, Version 1.0. #include <boost/hana/fwd/pair.hpp> -#include <boost/hana/basic_tuple.hpp> #include <boost/hana/config.hpp> #include <boost/hana/detail/decay.hpp> +#include <boost/hana/detail/ebo.hpp> #include <boost/hana/detail/intrinsics.hpp> #include <boost/hana/detail/operators/adl.hpp> #include <boost/hana/detail/operators/comparable.hpp> @@ -28,26 +28,37 @@ Distributed under the Boost Software License, Version 1.0. BOOST_HANA_NAMESPACE_BEGIN + namespace detail { + template <int> struct pix; // pair index + } + ////////////////////////////////////////////////////////////////////////// // pair ////////////////////////////////////////////////////////////////////////// //! @cond template <typename First, typename Second> - struct pair : detail::operators::adl<pair<First, Second>> { + struct pair : detail::operators::adl<pair<First, Second>> + , private detail::ebo<detail::pix<0>, First> + , private detail::ebo<detail::pix<1>, Second> + { + // Default constructor template <typename ...dummy, typename = typename std::enable_if< BOOST_HANA_TT_IS_CONSTRUCTIBLE(First, dummy...) && BOOST_HANA_TT_IS_CONSTRUCTIBLE(Second, dummy...) >::type> constexpr pair() - : storage_() + : detail::ebo<detail::pix<0>, First>() + , detail::ebo<detail::pix<1>, Second>() { } + // Variadic constructors template <typename ...dummy, typename = typename std::enable_if< BOOST_HANA_TT_IS_CONSTRUCTIBLE(First, First const&, dummy...) && BOOST_HANA_TT_IS_CONSTRUCTIBLE(Second, Second const&, dummy...) >::type> - constexpr pair(First const& first, Second const& second) - : storage_{first, second} + constexpr pair(First const& fst, Second const& snd) + : detail::ebo<detail::pix<0>, First>(fst) + , detail::ebo<detail::pix<1>, Second>(snd) { } template <typename T, typename U, typename = typename std::enable_if< @@ -55,34 +66,43 @@ BOOST_HANA_NAMESPACE_BEGIN BOOST_HANA_TT_IS_CONVERTIBLE(U&&, Second) >::type> constexpr pair(T&& t, U&& u) - : storage_{static_cast<T&&>(t), static_cast<U&&>(u)} + : detail::ebo<detail::pix<0>, First>(static_cast<T&&>(t)) + , detail::ebo<detail::pix<1>, Second>(static_cast<U&&>(u)) { } + + // Possibly converting copy and move constructors template <typename T, typename U, typename = typename std::enable_if< + BOOST_HANA_TT_IS_CONSTRUCTIBLE(First, T const&) && + BOOST_HANA_TT_IS_CONSTRUCTIBLE(Second, U const&) && BOOST_HANA_TT_IS_CONVERTIBLE(T const&, First) && BOOST_HANA_TT_IS_CONVERTIBLE(U const&, Second) >::type> constexpr pair(pair<T, U> const& other) - : storage_{hana::get_impl<0>(other.storage_), - hana::get_impl<1>(other.storage_)} + : detail::ebo<detail::pix<0>, First>(detail::ebo_get<detail::pix<0>>(other)) + , detail::ebo<detail::pix<1>, Second>(detail::ebo_get<detail::pix<1>>(other)) { } template <typename T, typename U, typename = typename std::enable_if< + BOOST_HANA_TT_IS_CONSTRUCTIBLE(First, T&&) && + BOOST_HANA_TT_IS_CONSTRUCTIBLE(Second, U&&) && BOOST_HANA_TT_IS_CONVERTIBLE(T&&, First) && BOOST_HANA_TT_IS_CONVERTIBLE(U&&, Second) >::type> constexpr pair(pair<T, U>&& other) - : storage_{static_cast<T&&>(hana::get_impl<0>(other.storage_)), - static_cast<U&&>(hana::get_impl<1>(other.storage_))} + : detail::ebo<detail::pix<0>, First>(static_cast<T&&>(detail::ebo_get<detail::pix<0>>(other))) + , detail::ebo<detail::pix<1>, Second>(static_cast<U&&>(detail::ebo_get<detail::pix<1>>(other))) { } + + // Copy and move assignment template <typename T, typename U, typename = typename std::enable_if< BOOST_HANA_TT_IS_ASSIGNABLE(First&, T const&) && BOOST_HANA_TT_IS_ASSIGNABLE(Second&, U const&) >::type> constexpr pair& operator=(pair<T, U> const& other) { - hana::get_impl<0>(storage_) = hana::get_impl<0>(other.storage_); - hana::get_impl<1>(storage_) = hana::get_impl<1>(other.storage_); + detail::ebo_get<detail::pix<0>>(*this) = detail::ebo_get<detail::pix<0>>(other); + detail::ebo_get<detail::pix<1>>(*this) = detail::ebo_get<detail::pix<1>>(other); return *this; } @@ -91,16 +111,26 @@ BOOST_HANA_NAMESPACE_BEGIN BOOST_HANA_TT_IS_ASSIGNABLE(Second&, U&&) >::type> constexpr pair& operator=(pair<T, U>&& other) { - hana::get_impl<0>(storage_) = static_cast<T&&>(hana::get_impl<0>(other.storage_)); - hana::get_impl<1>(storage_) = static_cast<U&&>(hana::get_impl<1>(other.storage_)); + detail::ebo_get<detail::pix<0>>(*this) = static_cast<T&&>(detail::ebo_get<detail::pix<0>>(other)); + detail::ebo_get<detail::pix<1>>(*this) = static_cast<U&&>(detail::ebo_get<detail::pix<1>>(other)); return *this; } - using hana_tag = pair_tag; - basic_tuple<First, Second> storage_; + // Prevent the compiler from defining the default copy and move + // constructors, which interfere with the SFINAE above. + ~pair() = default; + + friend struct first_impl<pair_tag>; + friend struct second_impl<pair_tag>; + template <typename F, typename S> friend struct pair; }; //! @endcond + template <typename First, typename Second> + struct tag_of<pair<First, Second>> { + using type = pair_tag; + }; + ////////////////////////////////////////////////////////////////////////// // Operators ////////////////////////////////////////////////////////////////////////// @@ -131,16 +161,46 @@ BOOST_HANA_NAMESPACE_BEGIN template <> struct first_impl<pair_tag> { - template <typename P> - static constexpr decltype(auto) apply(P&& p) - { return hana::get_impl<0>(static_cast<P&&>(p).storage_); } + template <typename First, typename Second> + static constexpr decltype(auto) apply(hana::pair<First, Second>& p) { + return detail::ebo_get<detail::pix<0>>( + static_cast<detail::ebo<detail::pix<0>, First>&>(p) + ); + } + template <typename First, typename Second> + static constexpr decltype(auto) apply(hana::pair<First, Second> const& p) { + return detail::ebo_get<detail::pix<0>>( + static_cast<detail::ebo<detail::pix<0>, First> const&>(p) + ); + } + template <typename First, typename Second> + static constexpr decltype(auto) apply(hana::pair<First, Second>&& p) { + return detail::ebo_get<detail::pix<0>>( + static_cast<detail::ebo<detail::pix<0>, First>&&>(p) + ); + } }; template <> struct second_impl<pair_tag> { - template <typename P> - static constexpr decltype(auto) apply(P&& p) - { return hana::get_impl<1>(static_cast<P&&>(p).storage_); } + template <typename First, typename Second> + static constexpr decltype(auto) apply(hana::pair<First, Second>& p) { + return detail::ebo_get<detail::pix<1>>( + static_cast<detail::ebo<detail::pix<1>, Second>&>(p) + ); + } + template <typename First, typename Second> + static constexpr decltype(auto) apply(hana::pair<First, Second> const& p) { + return detail::ebo_get<detail::pix<1>>( + static_cast<detail::ebo<detail::pix<1>, Second> const&>(p) + ); + } + template <typename First, typename Second> + static constexpr decltype(auto) apply(hana::pair<First, Second>&& p) { + return detail::ebo_get<detail::pix<1>>( + static_cast<detail::ebo<detail::pix<1>, Second>&&>(p) + ); + } }; BOOST_HANA_NAMESPACE_END |