functional.hpp 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. /* Copyright 2016-2018 Joaquin M Lopez Munoz.
  2. * Distributed under the Boost Software License, Version 1.0.
  3. * (See accompanying file LICENSE_1_0.txt or copy at
  4. * http://www.boost.org/LICENSE_1_0.txt)
  5. *
  6. * See http://www.boost.org/libs/poly_collection for library home page.
  7. */
  8. #ifndef BOOST_POLY_COLLECTION_DETAIL_FUNCTIONAL_HPP
  9. #define BOOST_POLY_COLLECTION_DETAIL_FUNCTIONAL_HPP
  10. #if defined(_MSC_VER)
  11. #pragma once
  12. #endif
  13. #include <boost/config.hpp>
  14. #include <boost/detail/workaround.hpp>
  15. #include <boost/mp11/integer_sequence.hpp>
  16. #include <tuple>
  17. #include <utility>
  18. /* Assorted functional utilities. Much of this would be almost trivial with
  19. * C++14 generic lambdas.
  20. */
  21. #if BOOST_WORKAROUND(BOOST_MSVC,>=1910)
  22. /* https://lists.boost.org/Archives/boost/2017/06/235687.php */
  23. #define BOOST_POLY_COLLECTION_DEFINE_OVERLOAD_SET(name,f) \
  24. struct name \
  25. { \
  26. template<typename... Args> \
  27. auto operator()(Args&&... args)const \
  28. { \
  29. return f(std::forward<Args>(args)...); \
  30. } \
  31. };
  32. #else
  33. #define BOOST_POLY_COLLECTION_DEFINE_OVERLOAD_SET(name,f) \
  34. struct name \
  35. { \
  36. template<typename... Args> \
  37. auto operator()(Args&&... args)const-> \
  38. decltype(f(std::forward<Args>(args)...)) \
  39. { \
  40. return f(std::forward<Args>(args)...); \
  41. } \
  42. };
  43. #endif
  44. namespace boost{
  45. namespace poly_collection{
  46. namespace detail{
  47. template<typename F,typename... TailArgs>
  48. struct tail_closure_class
  49. {
  50. tail_closure_class(const F& f,std::tuple<TailArgs...> t):f(f),t(t){}
  51. template<typename... Args>
  52. using return_type=decltype(
  53. std::declval<F>()(std::declval<Args>()...,std::declval<TailArgs>()...));
  54. template<typename... Args,std::size_t... I>
  55. return_type<Args&&...> call(mp11::index_sequence<I...>,Args&&... args)
  56. {
  57. return f(std::forward<Args>(args)...,std::get<I>(t)...);
  58. }
  59. template<typename... Args>
  60. return_type<Args&&...> operator()(Args&&... args)
  61. {
  62. return call(
  63. mp11::make_index_sequence<sizeof...(TailArgs)>{},
  64. std::forward<Args>(args)...);
  65. }
  66. F f;
  67. std::tuple<TailArgs...> t;
  68. };
  69. template<typename F,typename... Args>
  70. tail_closure_class<F,Args&&...> tail_closure(const F& f,Args&&... args)
  71. {
  72. return {f,std::forward_as_tuple(std::forward<Args>(args)...)};
  73. }
  74. template<typename F,typename... HeadArgs>
  75. struct head_closure_class
  76. {
  77. head_closure_class(const F& f,std::tuple<HeadArgs...> t):f(f),t(t){}
  78. template<typename... Args>
  79. using return_type=decltype(
  80. std::declval<F>()(std::declval<HeadArgs>()...,std::declval<Args>()...));
  81. template<typename... Args,std::size_t... I>
  82. return_type<Args&&...> call(mp11::index_sequence<I...>,Args&&... args)
  83. {
  84. return f(std::get<I>(t)...,std::forward<Args>(args)...);
  85. }
  86. template<typename... Args>
  87. return_type<Args&&...> operator()(Args&&... args)
  88. {
  89. return call(
  90. mp11::make_index_sequence<sizeof...(HeadArgs)>{},
  91. std::forward<Args>(args)...);
  92. }
  93. F f;
  94. std::tuple<HeadArgs...> t;
  95. };
  96. template<typename F,typename... Args>
  97. head_closure_class<F,Args&&...> head_closure(const F& f,Args&&... args)
  98. {
  99. return {f,std::forward_as_tuple(std::forward<Args>(args)...)};
  100. }
  101. template<typename ReturnType,typename F>
  102. struct cast_return_class
  103. {
  104. cast_return_class(const F& f):f(f){}
  105. template<typename... Args>
  106. ReturnType operator()(Args&&... args)const
  107. {
  108. return static_cast<ReturnType>(f(std::forward<Args>(args)...));
  109. }
  110. F f;
  111. };
  112. template<typename ReturnType,typename F>
  113. cast_return_class<ReturnType,F> cast_return(const F& f)
  114. {
  115. return {f};
  116. }
  117. template<typename F>
  118. struct deref_to_class
  119. {
  120. deref_to_class(const F& f):f(f){}
  121. template<typename... Args>
  122. auto operator()(Args&&... args)->decltype(std::declval<F>()(*args...))
  123. {
  124. return f(*args...);
  125. }
  126. F f;
  127. };
  128. template<typename F>
  129. deref_to_class<F> deref_to(const F& f)
  130. {
  131. return {f};
  132. }
  133. template<typename F>
  134. struct deref_1st_to_class
  135. {
  136. deref_1st_to_class(const F& f):f(f){}
  137. template<typename Arg,typename... Args>
  138. auto operator()(Arg&& arg,Args&&... args)
  139. ->decltype(std::declval<F>()(*arg,std::forward<Args>(args)...))
  140. {
  141. return f(*arg,std::forward<Args>(args)...);
  142. }
  143. F f;
  144. };
  145. template<typename F>
  146. deref_1st_to_class<F> deref_1st_to(const F& f)
  147. {
  148. return {f};
  149. }
  150. struct transparent_equal_to
  151. {
  152. template<typename T,typename U>
  153. auto operator()(T&& x,U&& y)const
  154. noexcept(noexcept(std::forward<T>(x)==std::forward<U>(y)))
  155. ->decltype(std::forward<T>(x)==std::forward<U>(y))
  156. {
  157. return std::forward<T>(x)==std::forward<U>(y);
  158. }
  159. };
  160. } /* namespace poly_collection::detail */
  161. } /* namespace poly_collection */
  162. } /* namespace boost */
  163. #endif