File indexing completed on 2025-01-18 09:38:14
0001
0002
0003
0004
0005
0006
0007
0008 #ifndef BOOST_HOF_GUARD_COMPRESSED_PAIR_H
0009 #define BOOST_HOF_GUARD_COMPRESSED_PAIR_H
0010
0011 #include <boost/hof/detail/delegate.hpp>
0012 #include <boost/hof/detail/move.hpp>
0013 #include <boost/hof/detail/forward.hpp>
0014 #include <boost/hof/config.hpp>
0015 #include <boost/hof/always.hpp>
0016 #include <boost/hof/alias.hpp>
0017
0018 #ifndef BOOST_HOF_COMPRESSED_PAIR_USE_EBO_WORKAROUND
0019 #define BOOST_HOF_COMPRESSED_PAIR_USE_EBO_WORKAROUND !BOOST_HOF_HAS_EBO
0020 #endif
0021
0022 namespace boost { namespace hof { namespace detail {
0023
0024 template<class First, class Second, class=void>
0025 struct compressed_pair;
0026
0027 template<int I, class T, class U>
0028 struct pair_tag
0029 {};
0030
0031 #if BOOST_HOF_COMPRESSED_PAIR_USE_EBO_WORKAROUND
0032
0033 template<class T, class U>
0034 struct is_same_template
0035 : std::false_type
0036 {};
0037
0038 template<template<class...> class X, class... Ts, class... Us>
0039 struct is_same_template<X<Ts...>, X<Us...>>
0040 : std::true_type
0041 {};
0042
0043 #if (defined(__GNUC__) && !defined (__clang__) && __GNUC__ == 4 && __GNUC_MINOR__ < 7)
0044
0045 template<class T, class U>
0046 struct is_related_template
0047 : std::false_type
0048 {};
0049
0050 #else
0051
0052 template<class T, class U>
0053 struct is_related_template
0054 : is_same_template<T, U>
0055 {};
0056
0057 #endif
0058
0059 template<class T, class U>
0060 struct is_related
0061 : std::integral_constant<bool, std::is_base_of<T, U>::value || std::is_base_of<U, T>::value || is_related_template<T, U>::value>
0062 {};
0063
0064 template<int I, class T, class U>
0065 struct pair_holder
0066 : std::conditional<(
0067 is_related<T, U>::value),
0068 detail::alias_empty<T, pair_tag<I, T, U>>,
0069 detail::alias_try_inherit<T, pair_tag<I, T, U>>
0070 >::type
0071 {};
0072 #else
0073 template<int I, class T, class U>
0074 struct pair_holder
0075 : detail::alias_try_inherit<T, pair_tag<I, T, U>>
0076 {};
0077 #endif
0078
0079
0080 template<
0081 class First,
0082 class Second
0083 >
0084 struct compressed_pair<First, Second>
0085 : pair_holder<0, First, Second>::type, pair_holder<1, Second, First>::type
0086 {
0087 typedef typename pair_holder<0, First, Second>::type first_base;
0088 typedef typename pair_holder<1, Second, First>::type second_base;
0089 template<class X, class Y,
0090 BOOST_HOF_ENABLE_IF_CONSTRUCTIBLE(First, X&&),
0091 BOOST_HOF_ENABLE_IF_CONSTRUCTIBLE(Second, Y&&)
0092 >
0093 constexpr compressed_pair(X&& x, Y&& y)
0094 noexcept(BOOST_HOF_IS_NOTHROW_CONSTRUCTIBLE(first_base, X&&) && BOOST_HOF_IS_NOTHROW_CONSTRUCTIBLE(second_base, Y&&))
0095 : first_base(BOOST_HOF_FORWARD(X)(x)), second_base(BOOST_HOF_FORWARD(Y)(y))
0096 {}
0097
0098 BOOST_HOF_INHERIT_DEFAULT(compressed_pair, first_base, second_base)
0099
0100 template<class Base, class... Xs>
0101 constexpr const Base& get_alias_base(Xs&&... xs) const noexcept
0102 {
0103 return boost::hof::always_ref(*this)(xs...);
0104 }
0105
0106 template<class... Xs>
0107 constexpr const First& first(Xs&&... xs) const noexcept
0108 {
0109 return boost::hof::alias_value(this->get_alias_base<first_base>(xs...), xs...);
0110 }
0111
0112 template<class... Xs>
0113 constexpr const Second& second(Xs&&... xs) const noexcept
0114 {
0115 return boost::hof::alias_value(this->get_alias_base<second_base>(xs...), xs...);
0116 }
0117
0118 };
0119
0120 template<class T, class U>
0121 constexpr compressed_pair<T, U> make_compressed_pair(T x, U y)
0122 noexcept(BOOST_HOF_IS_NOTHROW_MOVE_CONSTRUCTIBLE(T) && BOOST_HOF_IS_NOTHROW_MOVE_CONSTRUCTIBLE(U))
0123 {
0124 return {static_cast<T&&>(x), static_cast<U&&>(y)};
0125 }
0126
0127
0128 }}}
0129
0130 #endif