compressed_pair.hpp 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  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. #ifndef BOOST_HOF_GUARD_COMPRESSED_PAIR_H
  8. #define BOOST_HOF_GUARD_COMPRESSED_PAIR_H
  9. #include <boost/hof/detail/delegate.hpp>
  10. #include <boost/hof/detail/move.hpp>
  11. #include <boost/hof/detail/forward.hpp>
  12. #include <boost/hof/config.hpp>
  13. #include <boost/hof/always.hpp>
  14. #include <boost/hof/alias.hpp>
  15. #ifndef BOOST_HOF_COMPRESSED_PAIR_USE_EBO_WORKAROUND
  16. #define BOOST_HOF_COMPRESSED_PAIR_USE_EBO_WORKAROUND !BOOST_HOF_HAS_EBO
  17. #endif
  18. namespace boost { namespace hof { namespace detail {
  19. template<class First, class Second, class=void>
  20. struct compressed_pair;
  21. template<int I, class T, class U>
  22. struct pair_tag
  23. {};
  24. #if BOOST_HOF_COMPRESSED_PAIR_USE_EBO_WORKAROUND
  25. template<class T, class U>
  26. struct is_same_template
  27. : std::false_type
  28. {};
  29. template<template<class...> class X, class... Ts, class... Us>
  30. struct is_same_template<X<Ts...>, X<Us...>>
  31. : std::true_type
  32. {};
  33. #if (defined(__GNUC__) && !defined (__clang__) && __GNUC__ == 4 && __GNUC_MINOR__ < 7)
  34. template<class T, class U>
  35. struct is_related_template
  36. : std::false_type
  37. {};
  38. #else
  39. template<class T, class U>
  40. struct is_related_template
  41. : is_same_template<T, U>
  42. {};
  43. #endif
  44. template<class T, class U>
  45. struct is_related
  46. : std::integral_constant<bool, std::is_base_of<T, U>::value || std::is_base_of<U, T>::value || is_related_template<T, U>::value>
  47. {};
  48. template<int I, class T, class U>
  49. struct pair_holder
  50. : std::conditional<(
  51. is_related<T, U>::value),
  52. detail::alias_empty<T, pair_tag<I, T, U>>,
  53. detail::alias_try_inherit<T, pair_tag<I, T, U>>
  54. >::type
  55. {};
  56. #else
  57. template<int I, class T, class U>
  58. struct pair_holder
  59. : detail::alias_try_inherit<T, pair_tag<I, T, U>>
  60. {};
  61. #endif
  62. // TODO: Empty optimizations for MSVC
  63. template<
  64. class First,
  65. class Second
  66. >
  67. struct compressed_pair<First, Second>
  68. : pair_holder<0, First, Second>::type, pair_holder<1, Second, First>::type
  69. {
  70. typedef typename pair_holder<0, First, Second>::type first_base;
  71. typedef typename pair_holder<1, Second, First>::type second_base;
  72. template<class X, class Y,
  73. BOOST_HOF_ENABLE_IF_CONSTRUCTIBLE(First, X&&),
  74. BOOST_HOF_ENABLE_IF_CONSTRUCTIBLE(Second, Y&&)
  75. >
  76. constexpr compressed_pair(X&& x, Y&& y)
  77. noexcept(BOOST_HOF_IS_NOTHROW_CONSTRUCTIBLE(first_base, X&&) && BOOST_HOF_IS_NOTHROW_CONSTRUCTIBLE(second_base, Y&&))
  78. : first_base(BOOST_HOF_FORWARD(X)(x)), second_base(BOOST_HOF_FORWARD(Y)(y))
  79. {}
  80. BOOST_HOF_INHERIT_DEFAULT(compressed_pair, first_base, second_base)
  81. template<class Base, class... Xs>
  82. constexpr const Base& get_alias_base(Xs&&... xs) const noexcept
  83. {
  84. return boost::hof::always_ref(*this)(xs...);
  85. }
  86. template<class... Xs>
  87. constexpr const First& first(Xs&&... xs) const noexcept
  88. {
  89. return boost::hof::alias_value(this->get_alias_base<first_base>(xs...), xs...);
  90. }
  91. template<class... Xs>
  92. constexpr const Second& second(Xs&&... xs) const noexcept
  93. {
  94. return boost::hof::alias_value(this->get_alias_base<second_base>(xs...), xs...);
  95. }
  96. };
  97. template<class T, class U>
  98. constexpr compressed_pair<T, U> make_compressed_pair(T x, U y)
  99. noexcept(BOOST_HOF_IS_NOTHROW_MOVE_CONSTRUCTIBLE(T) && BOOST_HOF_IS_NOTHROW_MOVE_CONSTRUCTIBLE(U))
  100. {
  101. return {static_cast<T&&>(x), static_cast<U&&>(y)};
  102. }
  103. }}} // namespace boost::hof
  104. #endif