unpack_tuple.hpp 2.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  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