Advertisement
Kits

cartesian_product.cpp

Nov 7th, 2012
50
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.67 KB | None | 0 0
  1. #include <tuple>
  2. #include <utility>
  3. #include <algorithm>
  4. #include <memory>
  5. #include <vector>
  6. #include <set>
  7.  
  8. #include <iostream>
  9. #include <iterator>
  10. #include <ostream>
  11. #include <type_traits>
  12.  
  13. #include "tuples/for_each.hpp"
  14. #include "tuples/printer.hpp"
  15. #include "mpl/identity.hpp"
  16. #include "mpl/transform.hpp"
  17.  
  18. namespace mpl
  19. {
  20.  
  21.  
  22. template<typename T>
  23. struct container_type {
  24. typedef typename T::container_type type;
  25. };
  26.  
  27. template<typename T>
  28. struct value_type : T::value_type { };
  29.  
  30. template<bool B, typename T>
  31. struct iter_kind_h : identity<T> { };
  32.  
  33. template<typename T>
  34. struct iter_kind_h<true,T> : identity<typename T::container_type> { };
  35.  
  36. template<typename T>
  37. struct iter_kind : iter_kind_h< std::is_void<typename T::value_type>::value, T> { };
  38.  
  39. }
  40.  
  41. namespace algorithm
  42. {
  43.  
  44. namespace detail
  45. {
  46.  
  47. template<size_t N, typename tuple_type, typename Out>
  48. struct cartesian_product_impl
  49. {
  50. template<typename C, typename ... Containers>
  51. void operator()( Out& out, tuple_type tt_, C const& c, Containers const& ... containers )
  52. {
  53. for( auto it = c.begin() ; it != c.end(); ++it )
  54. {
  55. tuple_type tt( tt_ );
  56. ::std::get<N-sizeof...(Containers)-1>(tt) = *it;
  57. cartesian_product_impl<N, tuple_type, Out>()(out, tt, containers... );
  58. }
  59. }
  60.  
  61. template< typename C >
  62. void operator()( Out& out, tuple_type tt_, C const& c )
  63. {
  64. for( auto it = c.begin() ; it != c.end(); ++it )
  65. {
  66. tuple_type tt( tt_ );
  67. ::std::get<N-1>(tt) = *it;
  68. *out = tt;
  69. ++out;
  70. }
  71. }
  72. };
  73.  
  74. template< class Cont>
  75. struct get_value_type
  76. {
  77. typedef typename mpl::normalize<Cont>::type::value_type type;
  78. };
  79.  
  80. template<typename ... Containers>
  81. struct cartesian_product_value_type :
  82. mpl::transform<std::tuple<Containers...>, mpl::lambda<get_value_type> > { };
  83.  
  84.  
  85. } // deatil
  86.  
  87. size_t get_cartesian_size_( size_t init) { return init; }
  88. template< typename T, typename ... Args > size_t get_cartesian_size_( size_t init, T&&t, Args&&... args) { return get_cartesian_size_( init * t.size(), args... ); }
  89. template< typename T> size_t get_cartesian_size_( size_t init, T&&t ) { return init*t.size(); }
  90. template< typename T> size_t get_cartesian_size( T&&t ) { return t.size(); }
  91. template< typename T, typename ... Args > size_t get_cartesian_size( T&&t, Args&&... args) { return get_cartesian_size_( t.size(), args... ); }
  92. size_t get_cartesian_size() { return 0; }
  93.  
  94. template<
  95. typename OutIterator,
  96. typename ... Containers>
  97. struct cartesian_product
  98. {
  99. typedef typename detail::cartesian_product_value_type<Containers...>::type value_type;
  100.  
  101. cartesian_product( OutIterator& out, Containers&& ... in )
  102. {
  103. value_type t = {};
  104. detail::cartesian_product_impl< sizeof...(in), value_type, OutIterator >()
  105. ( out, t, in...);
  106. }
  107. };
  108.  
  109. template<
  110. typename OutIterator,
  111. typename ... Containers>
  112. void get_cartesian_product( OutIterator out, Containers&&... in )
  113. {
  114. static_assert( sizeof...(in) >= 1, "Cartesian product requires at least 1 container" );
  115. typedef typename detail::cartesian_product_value_type<Containers...>::type ResultValueType;
  116. typedef typename mpl::iter_kind< OutIterator >::type::value_type IteratorValueType;
  117. static_assert(
  118. std::is_same<
  119. ResultValueType,
  120. IteratorValueType
  121. >::value,
  122. "Output Iterator type does not match result type"
  123. );
  124. cartesian_product<OutIterator,Containers...>( out, in... );
  125. }
  126.  
  127. template<
  128. template<typename,typename...> class OutContainer,
  129. typename ... Containers>
  130. struct cartesian_product_create
  131. {
  132. typedef typename detail::cartesian_product_value_type<Containers...>::type value_type;
  133. typedef OutContainer< value_type > container_type;
  134. typedef typename container_type::iterator iterator;
  135.  
  136. container_type container;
  137.  
  138. iterator begin() { return container.begin(); }
  139. iterator end() { return container.end(); }
  140.  
  141. cartesian_product_create( Containers&& ... containers ) :
  142. container( get_cartesian_size( containers... ) )
  143. {
  144.  
  145. value_type t = {};
  146. iterator it = container.begin();
  147. detail::cartesian_product_impl< sizeof...(containers), value_type, iterator >()
  148. ( it, t, containers...);
  149. }
  150. };
  151.  
  152. template<
  153. template<typename,typename...> class OutContainer = std::vector,
  154. typename ... Containers>
  155. auto get_cartesian_product( Containers&&... in ) ->
  156. cartesian_product_create< OutContainer, Containers... >
  157. {
  158. static_assert( sizeof...(in) >= 1, "Cartesian product requires at least 1 container" );
  159. typedef typename detail::cartesian_product_value_type<Containers...>::type ResultValueType;
  160.  
  161. return cartesian_product_create<OutContainer,Containers...>( in... );
  162. }
  163.  
  164. } //algorithm
  165.  
  166. namespace std {
  167. using tuples::operator<<;
  168. }
  169.  
  170. int main()
  171. {
  172. using namespace std;
  173. vector<int> a;
  174. vector<const char*> b;
  175. vector<float> c;
  176.  
  177. a.push_back(1); a.push_back(2);
  178. b.push_back("Hello"); b.push_back("World");
  179. c.push_back(.1); c.push_back(.2);
  180.  
  181.  
  182. auto cs = algorithm::get_cartesian_product<vector>( a,b,c);
  183. typedef decltype(cs) cst;
  184. copy(cs.begin(), cs.end(), ostream_iterator<typename cst::value_type>(cout,"\n") );
  185. cout<<endl;
  186.  
  187. typedef tuple<int, const char*, float> tup;
  188. set< tup > z;
  189. algorithm::get_cartesian_product( inserter(z,z.begin()),a,b,c);
  190. copy(z.begin(), z.end(), ostream_iterator<tup>(cout,"\n") );
  191. cout<<endl;
  192.  
  193. vector< tup > y( algorithm::get_cartesian_size(a,b,c) );
  194. algorithm::get_cartesian_product(y.begin(),a,b,c);
  195. copy(y.begin(), y.end(), ostream_iterator<tup>(cout,"\n") );
  196. cout<<endl;
  197. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement