unpack.hpp 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. /*=============================================================================
  2. Copyright (c) 2015 Paul Fultz II
  3. unpack.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_UNPACK_H
  8. #define BOOST_HOF_GUARD_UNPACK_H
  9. /// unpack
  10. /// ======
  11. ///
  12. /// Description
  13. /// -----------
  14. ///
  15. /// The `unpack` function adaptor takes a sequence and uses the elements of
  16. /// the sequence for the arguments to the function. Multiple sequences can be
  17. /// passed to the function. All elements from each sequence will be passed
  18. /// into the function.
  19. ///
  20. ///
  21. /// Synopsis
  22. /// --------
  23. ///
  24. /// template<class F>
  25. /// unpack_adaptor<F> unpack(F f);
  26. ///
  27. /// Requirements
  28. /// ------------
  29. ///
  30. /// F must be:
  31. ///
  32. /// * [ConstInvocable](ConstInvocable)
  33. /// * MoveConstructible
  34. ///
  35. /// Example
  36. /// -------
  37. ///
  38. /// #include <boost/hof.hpp>
  39. /// #include <cassert>
  40. /// using namespace boost::hof;
  41. ///
  42. /// struct sum
  43. /// {
  44. /// template<class T, class U>
  45. /// T operator()(T x, U y) const
  46. /// {
  47. /// return x+y;
  48. /// }
  49. /// };
  50. ///
  51. /// int main() {
  52. /// int r = unpack(sum())(std::make_tuple(3,2));
  53. /// assert(r == 5);
  54. /// }
  55. ///
  56. /// References
  57. /// ----------
  58. ///
  59. /// * [std::apply](http://en.cppreference.com/w/cpp/utility/apply) - C++17 function to unpack a tuple
  60. /// * [`unpack_sequence`](unpack_sequence)
  61. ///
  62. #include <boost/hof/unpack_sequence.hpp>
  63. #include <boost/hof/is_unpackable.hpp>
  64. #include <boost/hof/detail/seq.hpp>
  65. #include <boost/hof/capture.hpp>
  66. #include <boost/hof/always.hpp>
  67. #include <boost/hof/reveal.hpp>
  68. #include <boost/hof/detail/and.hpp>
  69. #include <boost/hof/detail/delegate.hpp>
  70. #include <boost/hof/detail/holder.hpp>
  71. #include <boost/hof/detail/move.hpp>
  72. #include <boost/hof/detail/make.hpp>
  73. #include <boost/hof/detail/static_const_var.hpp>
  74. namespace boost { namespace hof {
  75. namespace detail {
  76. template<class F, class Sequence>
  77. constexpr auto unpack_simple(F&& f, Sequence&& s) BOOST_HOF_RETURNS
  78. (
  79. detail::unpack_impl(BOOST_HOF_FORWARD(F)(f), BOOST_HOF_FORWARD(Sequence)(s))
  80. )
  81. template<class F, class... Sequences>
  82. constexpr auto unpack_join(F&& f, Sequences&&... s) BOOST_HOF_RETURNS
  83. (
  84. boost::hof::pack_join(unpack_simple(boost::hof::pack_forward, BOOST_HOF_FORWARD(Sequences)(s))...)(BOOST_HOF_FORWARD(F)(f))
  85. );
  86. }
  87. template<class F>
  88. struct unpack_adaptor : detail::callable_base<F>
  89. {
  90. typedef unpack_adaptor fit_rewritable1_tag;
  91. BOOST_HOF_INHERIT_CONSTRUCTOR(unpack_adaptor, detail::callable_base<F>);
  92. template<class... Ts>
  93. constexpr const detail::callable_base<F>& base_function(Ts&&... xs) const noexcept
  94. {
  95. return boost::hof::always_ref(*this)(xs...);
  96. }
  97. struct unpack_failure
  98. {
  99. template<class Failure>
  100. struct apply
  101. {
  102. struct deducer
  103. {
  104. template<class... Ts>
  105. typename Failure::template of<Ts...> operator()(Ts&&...) const;
  106. };
  107. template<class T, class=typename std::enable_if<(
  108. is_unpackable<T>::value
  109. )>::type>
  110. static auto deduce(T&& x)
  111. BOOST_HOF_RETURNS
  112. (
  113. boost::hof::detail::unpack_simple(deducer(), BOOST_HOF_FORWARD(T)(x))
  114. );
  115. template<class T, class... Ts, class=typename std::enable_if<(
  116. is_unpackable<T>::value && BOOST_HOF_AND_UNPACK(is_unpackable<Ts>::value)
  117. )>::type>
  118. static auto deduce(T&& x, Ts&&... xs) BOOST_HOF_RETURNS
  119. (
  120. boost::hof::detail::unpack_join(deducer(), BOOST_HOF_FORWARD(T)(x), BOOST_HOF_FORWARD(Ts)(xs)...)
  121. );
  122. #ifdef _MSC_VER
  123. template<class... Ts>
  124. struct nop_failure;
  125. template<class... Ts, class=typename std::enable_if<(
  126. !BOOST_HOF_AND_UNPACK(is_unpackable<Ts>::value)
  127. )>::type>
  128. static as_failure<nop_failure> deduce(Ts&&... xs);
  129. #endif
  130. template<class... Ts>
  131. struct of
  132. #if (defined(__GNUC__) && !defined (__clang__) && __GNUC__ == 4 && __GNUC_MINOR__ < 7) || defined (_MSC_VER)
  133. : std::enable_if<true, decltype(apply::deduce(std::declval<Ts>()...))>::type
  134. #else
  135. : decltype(apply::deduce(std::declval<Ts>()...))
  136. #endif
  137. {};
  138. };
  139. };
  140. struct failure
  141. : failure_map<unpack_failure, detail::callable_base<F>>
  142. {};
  143. BOOST_HOF_RETURNS_CLASS(unpack_adaptor);
  144. template<class T, class=typename std::enable_if<(
  145. is_unpackable<T>::value
  146. )>::type>
  147. constexpr auto operator()(T&& x) const
  148. BOOST_HOF_RETURNS
  149. (
  150. boost::hof::detail::unpack_simple(BOOST_HOF_MANGLE_CAST(const detail::callable_base<F>&)(BOOST_HOF_CONST_THIS->base_function(x)), BOOST_HOF_FORWARD(T)(x))
  151. );
  152. template<class T, class... Ts, class=typename std::enable_if<(
  153. is_unpackable<T>::value && BOOST_HOF_AND_UNPACK(is_unpackable<Ts>::value)
  154. )>::type>
  155. constexpr auto operator()(T&& x, Ts&&... xs) const BOOST_HOF_RETURNS
  156. (
  157. boost::hof::detail::unpack_join(BOOST_HOF_MANGLE_CAST(const detail::callable_base<F>&)(BOOST_HOF_CONST_THIS->base_function(x)), BOOST_HOF_FORWARD(T)(x), BOOST_HOF_FORWARD(Ts)(xs)...)
  158. );
  159. };
  160. BOOST_HOF_DECLARE_STATIC_VAR(unpack, detail::make<unpack_adaptor>);
  161. }} // namespace boost::hof
  162. #endif