tuple.hpp 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  1. //
  2. // Copyright (c) 2016-2019 Damian Jarek (damian dot jarek93 at gmail dot com)
  3. // Copyright (c) 2022 Vinnie Falco (vinnie dot falco at gmail dot com)
  4. //
  5. // Distributed under the Boost Software License, Version 1.0. (See accompanying
  6. // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  7. //
  8. // Official repository: https://github.com/boostorg/beast
  9. //
  10. #ifndef BOOST_URL_GRAMMAR_DETAIL_TUPLE_HPP
  11. #define BOOST_URL_GRAMMAR_DETAIL_TUPLE_HPP
  12. #include <boost/url/detail/config.hpp>
  13. #include <boost/url/error_types.hpp>
  14. #include <boost/core/empty_value.hpp>
  15. #include <boost/mp11/algorithm.hpp>
  16. #include <boost/mp11/function.hpp>
  17. #include <boost/mp11/integer_sequence.hpp>
  18. #include <boost/type_traits/remove_cv.hpp>
  19. #include <boost/type_traits/copy_cv.hpp>
  20. #include <cstdlib>
  21. #include <utility>
  22. #ifndef BOOST_URL_TUPLE_EBO
  23. // VFALCO No idea what causes it or how to fix it
  24. // https://devblogs.microsoft.com/cppblog/optimizing-the-layout-of-empty-base-classes-in-vs2015-update-2-3/
  25. #ifdef BOOST_MSVC
  26. #define BOOST_URL_TUPLE_EBO 0
  27. #else
  28. #define BOOST_URL_TUPLE_EBO 1
  29. #endif
  30. #endif
  31. namespace boost {
  32. namespace urls {
  33. namespace grammar {
  34. namespace detail {
  35. #if BOOST_URL_TUPLE_EBO
  36. template<std::size_t I, class T>
  37. struct tuple_element_impl
  38. : empty_value<T>
  39. {
  40. constexpr
  41. tuple_element_impl(T const& t)
  42. : empty_value<T>(
  43. empty_init, t)
  44. {
  45. }
  46. constexpr
  47. tuple_element_impl(T&& t)
  48. : empty_value<T>(
  49. empty_init,
  50. std::move(t))
  51. {
  52. }
  53. };
  54. #else
  55. template<std::size_t I, class T>
  56. struct tuple_element_impl
  57. {
  58. T t_;
  59. constexpr
  60. tuple_element_impl(T const& t)
  61. : t_(t)
  62. {
  63. }
  64. constexpr
  65. tuple_element_impl(T&& t)
  66. : t_(std::move(t))
  67. {
  68. }
  69. constexpr
  70. T&
  71. get() noexcept
  72. {
  73. return t_;
  74. }
  75. constexpr
  76. T const&
  77. get() const noexcept
  78. {
  79. return t_;
  80. }
  81. };
  82. #endif
  83. template<std::size_t I, class T>
  84. struct tuple_element_impl<I, T&>
  85. {
  86. T& t;
  87. constexpr
  88. tuple_element_impl(T& t_)
  89. : t(t_)
  90. {
  91. }
  92. T&
  93. get() const noexcept
  94. {
  95. return t;
  96. }
  97. };
  98. template<class... Ts>
  99. struct tuple_impl;
  100. template<class... Ts, std::size_t... Is>
  101. struct tuple_impl<
  102. mp11::index_sequence<Is...>, Ts...>
  103. : tuple_element_impl<Is, Ts>...
  104. {
  105. template<class... Us>
  106. constexpr
  107. explicit
  108. tuple_impl(Us&&... us)
  109. : tuple_element_impl<Is, Ts>(
  110. std::forward<Us>(us))...
  111. {
  112. }
  113. };
  114. template<class... Ts>
  115. struct tuple
  116. : tuple_impl<
  117. mp11::index_sequence_for<Ts...>, Ts...>
  118. {
  119. template<class... Us,
  120. typename std::enable_if<
  121. mp11::mp_bool<
  122. mp11::mp_all<std::is_constructible<
  123. Ts, Us>...>::value &&
  124. ! mp11::mp_all<std::is_convertible<
  125. Us, Ts>...>::value>::value,
  126. int>::type = 0
  127. >
  128. constexpr
  129. explicit
  130. tuple(Us&&... us) noexcept
  131. : tuple_impl<mp11::index_sequence_for<
  132. Ts...>, Ts...>{std::forward<Us>(us)...}
  133. {
  134. }
  135. template<class... Us,
  136. typename std::enable_if<
  137. mp11::mp_all<std::is_convertible<
  138. Us, Ts>...>::value,
  139. int>::type = 0
  140. >
  141. constexpr
  142. tuple(Us&&... us) noexcept
  143. : tuple_impl<mp11::index_sequence_for<
  144. Ts...>, Ts...>{std::forward<Us>(us)...}
  145. {
  146. }
  147. };
  148. //------------------------------------------------
  149. template<std::size_t I, class T>
  150. constexpr
  151. T&
  152. get(tuple_element_impl<I, T>& te)
  153. {
  154. return te.get();
  155. }
  156. template<std::size_t I, class T>
  157. constexpr
  158. T const&
  159. get(tuple_element_impl<I, T> const& te)
  160. {
  161. return te.get();
  162. }
  163. template<std::size_t I, class T>
  164. constexpr
  165. T&&
  166. get(tuple_element_impl<I, T>&& te)
  167. {
  168. return std::move(te.get());
  169. }
  170. template<std::size_t I, class T>
  171. constexpr
  172. T&
  173. get(tuple_element_impl<I, T&>&& te)
  174. {
  175. return te.get();
  176. }
  177. template<std::size_t I, class T>
  178. using tuple_element =
  179. typename boost::copy_cv<
  180. mp11::mp_at_c<typename
  181. remove_cv<T>::type,
  182. I>, T>::type;
  183. } // detail
  184. } // grammar
  185. } // urls
  186. } // boost
  187. #endif