fork download
  1. #include <tuple>
  2.  
  3. // basic sequences
  4. template<unsigned...> struct seq {};
  5. template<unsigned max, unsigned...s> struct make_seq:make_seq<max-1, max-1, s...> {};
  6. template<unsigned...s> struct make_seq<0,s...>:seq<s...> {};
  7.  
  8. #define RETURNS(x) ->decltype(x) { return (x); }
  9.  
  10. template<typename Iterator>
  11. struct simple_range {
  12. Iterator begin;
  13. Iterator end;
  14. typedef Iterator iterator;
  15. };
  16. template<typename Iterator>
  17. auto begin( simple_range<Iterator> r )
  18. RETURNS( r.begin )
  19. template<typename Iterator>
  20. auto end( simple_range<Iterator> r )
  21. RETURNS( r.end )
  22.  
  23. template<typename... Ranges>
  24. struct cartesian_range {
  25. std::tuple<Ranges...> ranges;
  26. };
  27. // TODO: wrap this in boost iterator fascade:
  28. template<typename... Ranges>
  29. struct cartesian_iterator {
  30. cartesian_range<Ranges...> ranges;
  31. std::tuple<typename Ranges::iterator...> iterators;
  32. explicit cartesian_iterator( typename Ranges::iterator... its ):
  33. iterators(its...)
  34. {}
  35. template<unsigned...s>
  36. auto dereference_helper(seq<s...>)
  37. RETURNS( std::make_tuple( *std::get<s>(iterators)... ) )
  38. auto dereference()
  39. RETURNS( dereference_helper( make_seq<sizeof...(Ranges)>() ) )
  40. bool is_equal( cartesian_iterator<Ranges...> const& o ) {
  41. return iterators == o.iterators;
  42. }
  43. void advance_helper(seq<>) {}
  44. template<unsigned s0, unsigned...s>
  45. void advance_helper(seq<s0, s...>) {
  46. ++std::get<s0>(iterators);
  47. auto it0 = std::get<s0>( iterators );
  48. auto end0 = end(std::get<s0>(ranges));
  49. if (it0 == end0)
  50. {
  51. auto begin0 = begin( std::get<s0>(ranges) );
  52. std::get<s0>(iterators) = begin0;
  53. advance_helper( seq<s...>() );
  54. }
  55. }
  56. void advance() {
  57. advance_helper( make_seq<sizeof...(Ranges)>() );
  58. }
  59. };
  60. template<typename... Iterators>
  61. cartesian_iterator<simple_range<Iterators>...> make_cartesian_iterator( Iterators... its )
  62. {
  63. return {its...};
  64. }
  65. template<unsigned... s, typename... Ranges>
  66. auto begin_helper( seq<s...>, cartesian_range<Ranges...> r )
  67. RETURNS( make_cartesian_iterator( begin(std::get<s>(r))... ) )
  68. template<unsigned... s, typename... Ranges>
  69. auto end_helper( seq<s...>, cartesian_range<Ranges...> r )
  70. RETURNS( make_cartesian_iterator( end(std::get<s>(r))... ) )
  71.  
  72. template<typename... Ranges>
  73. auto begin( cartesian_range<Ranges...> r )
  74. RETURNS( begin_helper( make_seq<sizeof...(Ranges)>(), r ) )
  75. template<typename... Ranges>
  76. auto end( cartesian_range<Ranges...> r )
  77. RETURNS( end_helper( make_seq<sizeof...(Ranges)>(), r ) )
  78.  
  79.  
Compilation error #stdin compilation error #stdout 0s 0KB
stdin
Standard input is empty
compilation info
/usr/lib/gcc/i486-linux-gnu/4.8/../../../i386-linux-gnu/crt1.o: In function `_start':
(.text+0x18): undefined reference to `main'
collect2: error: ld returned 1 exit status
stdout
Standard output is empty