type_restitution.hpp 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  1. /* Copyright 2016-2017 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_TYPE_RESTITUTION_HPP
  9. #define BOOST_POLY_COLLECTION_DETAIL_TYPE_RESTITUTION_HPP
  10. #if defined(_MSC_VER)
  11. #pragma once
  12. #endif
  13. #include <boost/poly_collection/detail/functional.hpp>
  14. #include <boost/poly_collection/detail/iterator_traits.hpp>
  15. #include <typeinfo>
  16. #include <utility>
  17. namespace boost{
  18. namespace poly_collection{
  19. namespace detail{
  20. /* Given types Ts..., a const std::type_info& info and a local_base_iterator
  21. * it, we denote by restitute<Ts...>(info,it):
  22. * - a local_iterator<Ti> from it, if info==typeid(Ti) for some Ti in Ts...
  23. * - it otherwise.
  24. *
  25. * Using this notation, restitute_range<Ts...>(f,args...)(s) resolves to
  26. * f(restitute<Ts...>(info,begin),restitute<Ts...>(info,end),args...) where
  27. * info=s.type_info(), begin=s.begin(), end=s.end().
  28. */
  29. template<typename F,typename... Ts>
  30. struct restitute_range_class;
  31. template<typename F,typename T,typename... Ts>
  32. struct restitute_range_class<F,T,Ts...>:
  33. restitute_range_class<F,Ts...>
  34. {
  35. using super=restitute_range_class<F,Ts...>;
  36. using super::super;
  37. template<typename SegmentInfo>
  38. auto operator()(SegmentInfo&& s)
  39. ->decltype(std::declval<F>()(s.begin(),s.end()))
  40. {
  41. using traits=iterator_traits<decltype(s.begin())>;
  42. using local_iterator=typename traits::template local_iterator<T>;
  43. if(s.type_info()==typeid(T))
  44. return (this->f)(
  45. local_iterator{s.begin()},local_iterator{s.end()});
  46. else
  47. return super::operator()(std::forward<SegmentInfo>(s));
  48. }
  49. };
  50. template<typename F>
  51. struct restitute_range_class<F>
  52. {
  53. restitute_range_class(const F& f):f(f){}
  54. template<typename SegmentInfo>
  55. auto operator()(SegmentInfo&& s)
  56. ->decltype(std::declval<F>()(s.begin(),s.end()))
  57. {
  58. return f(s.begin(),s.end());
  59. }
  60. F f;
  61. };
  62. template<typename... Ts,typename F,typename... Args>
  63. auto restitute_range(const F& f,Args&&... args)
  64. ->restitute_range_class<
  65. decltype(tail_closure(f,std::forward<Args>(args)...)),
  66. Ts...
  67. >
  68. {
  69. return tail_closure(f,std::forward<Args>(args)...);
  70. }
  71. /* restitute_iterator<Ts...>(f,args2...)(index,it,args1...) resolves to
  72. * f(restitute<Ts...>(index,it),args1...,args2...).
  73. */
  74. template<typename F,typename... Ts>
  75. struct restitute_iterator_class;
  76. template<typename F,typename T,typename... Ts>
  77. struct restitute_iterator_class<F,T,Ts...>:
  78. restitute_iterator_class<F,Ts...>
  79. {
  80. using super=restitute_iterator_class<F,Ts...>;
  81. using super::super;
  82. template<typename Iterator,typename... Args>
  83. auto operator()(
  84. const std::type_info& info,Iterator&& it,Args&&... args)
  85. ->decltype(
  86. std::declval<F>()
  87. (std::forward<Iterator>(it),std::forward<Args>(args)...))
  88. {
  89. using traits=iterator_traits<typename std::decay<Iterator>::type>;
  90. using local_iterator=typename traits::template local_iterator<T>;
  91. if(info==typeid(T))
  92. return (this->f)(
  93. local_iterator{it},std::forward<Args>(args)...);
  94. else
  95. return super::operator()(
  96. info,std::forward<Iterator>(it),std::forward<Args>(args)...);
  97. }
  98. };
  99. template<typename F>
  100. struct restitute_iterator_class<F>
  101. {
  102. restitute_iterator_class(const F& f):f(f){}
  103. template<typename Iterator,typename... Args>
  104. auto operator()(
  105. const std::type_info&,Iterator&& it,Args&&... args)
  106. ->decltype(
  107. std::declval<F>()
  108. (std::forward<Iterator>(it),std::forward<Args>(args)...))
  109. {
  110. return f(std::forward<Iterator>(it),std::forward<Args>(args)...);
  111. }
  112. F f;
  113. };
  114. template<typename... Ts,typename F,typename... Args>
  115. auto restitute_iterator(const F& f,Args&&... args)
  116. ->restitute_iterator_class<
  117. decltype(tail_closure(f,std::forward<Args>(args)...)),
  118. Ts...
  119. >
  120. {
  121. return tail_closure(f,std::forward<Args>(args)...);
  122. }
  123. /* binary_restitute_iterator<Ts...>(f,args...)(index1,it1,index2,it2) resolves
  124. * to f(restitute<Ts...>(index1,it1),restitute<Ts...>(index2,it2),args...).
  125. */
  126. template<typename F,typename... Ts>
  127. struct binary_restitute_iterator_class
  128. {
  129. binary_restitute_iterator_class(const F& f):f(f){}
  130. template<typename Iterator1,typename Iterator2>
  131. auto operator()(
  132. const std::type_info& info1,Iterator1&& it1,
  133. const std::type_info& info2,Iterator2&& it2)
  134. ->decltype(
  135. std::declval<F>()
  136. (std::forward<Iterator1>(it1),std::forward<Iterator2>(it2)))
  137. {
  138. return restitute_iterator<Ts...>(*this)(
  139. info2,std::forward<Iterator2>(it2),info1,std::forward<Iterator1>(it1));
  140. }
  141. template<typename Iterator2,typename Iterator1>
  142. auto operator()(
  143. Iterator2&& it2,const std::type_info& info1,Iterator1&& it1)
  144. ->decltype(
  145. std::declval<F>()
  146. (std::forward<Iterator1>(it1),std::forward<Iterator2>(it2)))
  147. {
  148. return restitute_iterator<Ts...>(f)(
  149. info1,std::forward<Iterator1>(it1),std::forward<Iterator2>(it2));
  150. }
  151. F f;
  152. };
  153. template<typename... Ts,typename F,typename... Args>
  154. auto binary_restitute_iterator(const F& f,Args&&... args)
  155. ->binary_restitute_iterator_class<
  156. decltype(tail_closure(f,std::forward<Args>(args)...)),
  157. Ts...
  158. >
  159. {
  160. return tail_closure(f,std::forward<Args>(args)...);
  161. }
  162. } /* namespace poly_collection::detail */
  163. } /* namespace poly_collection */
  164. } /* namespace boost */
  165. #endif