fork download
  1. #include <type_traits>
  2. #include <unordered_map>
  3. #include <vector>
  4. #include <queue>
  5. #include <iostream>
  6. #include <map>
  7. #include <memory>
  8. #include <functional>
  9. #include <cmath>
  10. #include <list>
  11.  
  12. #include <boost/iterator/transform_iterator.hpp>
  13. #include <boost/core/demangle.hpp>
  14.  
  15. namespace xstd
  16. {
  17. template <typename Container>
  18. struct container_traits
  19. {
  20.  
  21. };
  22.  
  23. template <template <typename, typename> typename ValueContainer,
  24. typename Value,
  25. typename Allocator>
  26. struct container_traits<ValueContainer<Value, Allocator>> {
  27. using container_type = ValueContainer<Value, Allocator>;
  28. using allocator_type = typename container_type::allocator_type;
  29. using allocator_traits = std::allocator_traits<allocator_type>;
  30.  
  31. using value_type = Value;
  32.  
  33. template <typename U>
  34. using rebound_allocator_type = typename allocator_traits::template rebind_alloc<U>;
  35.  
  36. template <typename U>
  37. using rebound_container_type = ValueContainer<U, rebound_allocator_type<U>>;
  38. };
  39.  
  40. template <template <typename, typename, typename, typename> typename KeyValueContainer,
  41. typename Key,
  42. typename Value,
  43. template <typename> typename Less,
  44. typename Allocator>
  45. struct container_traits<KeyValueContainer<Key, Value, Less<Key>, Allocator>> {
  46. using container_type = KeyValueContainer<Key, Value, Less<Key>, Allocator>;
  47. using allocator_type = typename container_type::allocator_type;
  48. using less_type = Less<Key>;
  49. using allocator_traits = std::allocator_traits<allocator_type>;
  50.  
  51. using key_type = Key;
  52. using value_type = Value;
  53.  
  54. template <typename U>
  55. using rebound_allocator_type = typename allocator_traits::template rebind_alloc<U>;
  56.  
  57. template <typename U>
  58. using rebound_compare_type = Less<U>;
  59.  
  60. template <typename T, typename U>
  61. using rebound_kv_container_type = KeyValueContainer<T, U, rebound_compare_type<T>, rebound_allocator_type<std::pair<T, U>>>;
  62.  
  63. template <typename T,
  64. typename U = rebound_allocator_type<T>,
  65. template <typename, typename> typename Container = std::vector>
  66. using rebound_container_type = Container<T, U>;
  67. };
  68.  
  69.  
  70. template <template <typename, size_t> typename Container, typename T, size_t N>
  71. struct container_traits<Container<T, N>>
  72. {
  73. using container_type = Container<T, N>;
  74. using value_type = T;
  75. constexpr static const size_t arity = N;
  76.  
  77. template <typename U>
  78. using rebound_container_type = Container<U, arity>;
  79. };
  80.  
  81. template <typename T,
  82. typename Container,
  83. typename U>
  84. auto transform(Container const& source, std::function<U(T*)> fn)
  85. -> std::enable_if<
  86. std::is_same<
  87. typename container_traits<Container>::value_type,
  88. typename std::add_pointer<T>::type
  89. >::value,
  90. typename container_traits<Container>::template rebound_container_type<U>
  91. > {
  92. auto begin = boost::make_transform_iterator(source.begin(), fn);
  93. auto end = boost::make_transform_iterator(source.end(), fn);
  94.  
  95. using target_t = typename container_traits<Container>::template rebound_container_type<U>;
  96. target_t transformed(begin, end);
  97. return transformed;
  98. }
  99.  
  100. template <typename T,
  101. typename Container,
  102. typename U>
  103. auto transform(Container const& source, std::function<U(T const&)> fn)
  104. -> typename container_traits<Container>::template rebound_container_type<U> {
  105. auto begin = boost::make_transform_iterator(source.begin(), fn);
  106. auto end = boost::make_transform_iterator(source.end(), fn);
  107.  
  108. using target_t = typename container_traits<Container>::template rebound_container_type<U>;
  109. target_t transformed(begin, end);
  110. return transformed;
  111. }
  112.  
  113. // Resolves for free-standing function pointer arguments
  114. template <typename U, typename Container, typename T>
  115. auto transform(Container const& source, U (*fn)(T))
  116. -> typename container_traits<Container>::template rebound_container_type<U> {
  117. auto begin = boost::make_transform_iterator(source.begin(), fn);
  118. auto end = boost::make_transform_iterator(source.end(), fn);
  119.  
  120. using target_t = typename container_traits<Container>::template rebound_container_type<U>;
  121. target_t transformed(begin, end);
  122. return transformed;
  123. }
  124.  
  125. template <typename Container, typename Transform>
  126. auto transform(Container const& source, Transform fn)
  127. -> typename container_traits<Container>::template rebound_container_type<
  128. typename std::result_of<Transform(typename container_traits<Container>::value_type)>::type
  129. > {
  130. auto begin = boost::make_transform_iterator(source.begin(), fn);
  131. auto end = boost::make_transform_iterator(source.end(), fn);
  132.  
  133. using U = typename std::result_of<Transform(typename container_traits<Container>::value_type)>::type;
  134.  
  135. using target_t = typename container_traits<Container>::template rebound_container_type<U>;
  136. target_t transformed(begin, end);
  137. return transformed;
  138. }
  139.  
  140. template <template <typename, size_t> typename Container, typename T, size_t N, typename Transform>
  141. auto transform(Container<T, N> const& source, Transform fn)
  142. -> typename container_traits<Container<T, N>>::template rebound_container_type<
  143. typename std::result_of<Transform(typename container_traits<Container<T, N>>::value_type)>::type
  144. > {
  145.  
  146. using U = typename std::result_of<Transform(typename container_traits<Container<T, N>>::value_type)>::type;
  147.  
  148. using target_t = typename container_traits<Container<T, N>>::template rebound_container_type<U>;
  149. target_t transformed;
  150.  
  151. for (size_t i = 0; i < N; ++i) {
  152. transformed[i] = fn(source[i]);
  153. }
  154.  
  155. return transformed;
  156. }
  157. }
  158.  
  159. int round(float f) { return std::round(f); }
  160.  
  161. int main()
  162. {
  163. using vint_trait = xstd::container_traits<std::vector<int>>;
  164. using ftype = typename vint_trait::template rebound_container_type<float>;
  165.  
  166. using mintfloat_trait = xstd::container_traits<std::map<int, float>>;
  167. using miftype = typename mintfloat_trait::template rebound_kv_container_type<float, int>;
  168.  
  169. using mitype = typename mintfloat_trait::template rebound_container_type<float>;
  170.  
  171. std::cout << boost::core::demangle(typeid(ftype).name()) << std::endl;
  172. std::cout << boost::core::demangle(typeid(miftype).name()) << std::endl;
  173. std::cout << boost::core::demangle(typeid(mitype).name()) << std::endl;
  174.  
  175. {
  176. std::vector<int> is { 1, 2, 3, 4, 5 };
  177. std::vector<float> fs = xstd::transform(is, [](int i) -> float { return float(0.5f + i); });
  178. for (auto&& itr : fs) {
  179. std::cout << itr << " ";
  180. }std::cout << std::endl;
  181. }
  182.  
  183. {
  184. std::array<int, 5> ia { 1, 2, 3, 4, 5 };
  185. std::array<float, 5> fa = xstd::transform(ia, [](int i) -> float { return float(0.75f + i); });
  186. for (auto&& itr : fa) {
  187. std::cout << itr << " ";
  188. }
  189. std::cout << std::endl;
  190. }
  191. return 0;
  192. }
  193.  
Success #stdin #stdout 0s 15240KB
stdin
Standard input is empty
stdout
std::vector<float, std::allocator<float> >
std::map<float, int, std::less<float>, std::allocator<std::pair<float, int> > >
std::vector<float, std::allocator<float> >
1.5 2.5 3.5 4.5 5.5 
1.75 2.75 3.75 4.75 5.75