unpack_tuple.hpp 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. /*=============================================================================
  2. Copyright (c) 2016 Paul Fultz II
  3. unpack_tuple.hpp
  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_UNPACK_TUPLE_HPP
  8. #define BOOST_HOF_GUARD_UNPACK_TUPLE_HPP
  9. #include <boost/hof/unpack_sequence.hpp>
  10. #include <boost/hof/returns.hpp>
  11. #include <boost/hof/detail/forward.hpp>
  12. #include <boost/hof/detail/seq.hpp>
  13. #include <tuple>
  14. #include <array>
  15. namespace boost { namespace hof {
  16. namespace detail {
  17. template<class Sequence>
  18. constexpr typename gens<std::tuple_size<Sequence>::value>::type
  19. make_tuple_gens(const Sequence&)
  20. {
  21. return {};
  22. }
  23. #if (defined(__GNUC__) && !defined (__clang__) && __GNUC__ == 4 && __GNUC_MINOR__ < 7)
  24. template<std::size_t I, class Tuple>
  25. struct tuple_element_return
  26. : std::tuple_element<I, Tuple>
  27. {};
  28. template<std::size_t I, class Tuple>
  29. struct tuple_element_return<I, Tuple&>
  30. : std::add_lvalue_reference<typename tuple_element_return<I, Tuple>::type>
  31. {};
  32. template<std::size_t I, class Tuple>
  33. struct tuple_element_return<I, Tuple&&>
  34. : std::add_rvalue_reference<typename tuple_element_return<I, Tuple>::type>
  35. {};
  36. template<std::size_t I, class Tuple>
  37. struct tuple_element_return<I, const Tuple>
  38. : std::add_const<typename tuple_element_return<I, Tuple>::type>
  39. {};
  40. template< std::size_t I, class Tuple, class R = typename tuple_element_return<I, Tuple&&>::type >
  41. R tuple_get( Tuple&& t )
  42. {
  43. return (R&&)(std::get<I>(boost::hof::forward<Tuple>(t)));
  44. }
  45. #define BOOST_HOF_UNPACK_TUPLE_GET boost::hof::detail::tuple_get
  46. #else
  47. #define BOOST_HOF_UNPACK_TUPLE_GET std::get
  48. #endif
  49. template<class F, class T, std::size_t ...N>
  50. constexpr auto unpack_tuple(F&& f, T&& t, seq<N...>) BOOST_HOF_RETURNS
  51. (
  52. f(
  53. BOOST_HOF_AUTO_FORWARD(BOOST_HOF_UNPACK_TUPLE_GET<N>(BOOST_HOF_AUTO_FORWARD(t)))...
  54. )
  55. );
  56. struct unpack_tuple_apply
  57. {
  58. template<class F, class S>
  59. constexpr static auto apply(F&& f, S&& t) BOOST_HOF_RETURNS
  60. (
  61. boost::hof::detail::unpack_tuple(BOOST_HOF_FORWARD(F)(f), BOOST_HOF_FORWARD(S)(t), boost::hof::detail::make_tuple_gens(t))
  62. );
  63. };
  64. }
  65. template<class... Ts>
  66. struct unpack_sequence<std::tuple<Ts...>>
  67. : detail::unpack_tuple_apply
  68. {};
  69. template<class T, class U>
  70. struct unpack_sequence<std::pair<T, U>>
  71. : detail::unpack_tuple_apply
  72. {};
  73. template<class T, std::size_t N>
  74. struct unpack_sequence<std::array<T, N>>
  75. : detail::unpack_tuple_apply
  76. {};
  77. }} // namespace boost::hof
  78. #endif