1 /*============================================================================= 2 Copyright (c) 2015 Paul Fultz II 3 compressed_pair.h 4 Distributed under the Boost Software License, Version 1.0. (See accompanying 5 file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 6 ==============================================================================*/ 7 8 #ifndef BOOST_HOF_GUARD_COMPRESSED_PAIR_H 9 #define BOOST_HOF_GUARD_COMPRESSED_PAIR_H 10 11 #include <boost/hof/detail/delegate.hpp> 12 #include <boost/hof/detail/move.hpp> 13 #include <boost/hof/detail/forward.hpp> 14 #include <boost/hof/config.hpp> 15 #include <boost/hof/always.hpp> 16 #include <boost/hof/alias.hpp> 17 18 #ifndef BOOST_HOF_COMPRESSED_PAIR_USE_EBO_WORKAROUND 19 #define BOOST_HOF_COMPRESSED_PAIR_USE_EBO_WORKAROUND !BOOST_HOF_HAS_EBO 20 #endif 21 22 namespace boost { namespace hof { namespace detail { TEST(DecisionLogic,CreateAndDestroy)23 24 template<class First, class Second, class=void> 25 struct compressed_pair; 26 27 template<int I, class T, class U> 28 struct pair_tag 29 {}; 30 31 #if BOOST_HOF_COMPRESSED_PAIR_USE_EBO_WORKAROUND 32 33 template<class T, class U> 34 struct is_same_template 35 : std::false_type 36 {}; 37 38 template<template<class...> class X, class... Ts, class... Us> 39 struct is_same_template<X<Ts...>, X<Us...>> 40 : std::true_type 41 {}; 42 43 #if (defined(__GNUC__) && !defined (__clang__) && __GNUC__ == 4 && __GNUC_MINOR__ < 7) 44 45 template<class T, class U> 46 struct is_related_template 47 : std::false_type 48 {}; 49 50 #else 51 52 template<class T, class U> 53 struct is_related_template 54 : is_same_template<T, U> 55 {}; 56 57 #endif 58 59 template<class T, class U> 60 struct is_related 61 : std::integral_constant<bool, std::is_base_of<T, U>::value || std::is_base_of<U, T>::value || is_related_template<T, U>::value> 62 {}; 63 64 template<int I, class T, class U> 65 struct pair_holder 66 : std::conditional<( 67 is_related<T, U>::value), 68 detail::alias_empty<T, pair_tag<I, T, U>>, 69 detail::alias_try_inherit<T, pair_tag<I, T, U>> 70 >::type 71 {}; 72 #else 73 template<int I, class T, class U> 74 struct pair_holder 75 : detail::alias_try_inherit<T, pair_tag<I, T, U>> 76 {}; 77 #endif 78 79 // TODO: Empty optimizations for MSVC 80 template< 81 class First, 82 class Second 83 > 84 struct compressed_pair<First, Second> 85 : pair_holder<0, First, Second>::type, pair_holder<1, Second, First>::type 86 { 87 typedef typename pair_holder<0, First, Second>::type first_base; 88 typedef typename pair_holder<1, Second, First>::type second_base; 89 template<class X, class Y, 90 BOOST_HOF_ENABLE_IF_CONSTRUCTIBLE(First, X&&), 91 BOOST_HOF_ENABLE_IF_CONSTRUCTIBLE(Second, Y&&) 92 > 93 constexpr compressed_pair(X&& x, Y&& y) 94 noexcept(BOOST_HOF_IS_NOTHROW_CONSTRUCTIBLE(first_base, X&&) && BOOST_HOF_IS_NOTHROW_CONSTRUCTIBLE(second_base, Y&&)) 95 : first_base(BOOST_HOF_FORWARD(X)(x)), second_base(BOOST_HOF_FORWARD(Y)(y)) 96 {} 97 98 BOOST_HOF_INHERIT_DEFAULT(compressed_pair, first_base, second_base) 99 100 template<class Base, class... Xs> 101 constexpr const Base& get_alias_base(Xs&&... xs) const noexcept 102 { 103 return boost::hof::always_ref(*this)(xs...); 104 } 105 106 template<class... Xs> 107 constexpr const First& first(Xs&&... xs) const noexcept 108 { 109 return boost::hof::alias_value(this->get_alias_base<first_base>(xs...), xs...); 110 } 111 112 template<class... Xs> 113 constexpr const Second& second(Xs&&... xs) const noexcept 114 { 115 return boost::hof::alias_value(this->get_alias_base<second_base>(xs...), xs...); 116 } 117 118 }; 119 120 template<class T, class U> 121 constexpr compressed_pair<T, U> make_compressed_pair(T x, U y) 122 noexcept(BOOST_HOF_IS_NOTHROW_MOVE_CONSTRUCTIBLE(T) && BOOST_HOF_IS_NOTHROW_MOVE_CONSTRUCTIBLE(U)) 123 { 124 return {static_cast<T&&>(x), static_cast<U&&>(y)}; 125 } 126 127 128 }}} // namespace boost::hof 129 130 #endif 131