Dukales

multiarray

Jun 25th, 2015
351
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 8.15 KB | None | 0 0
  1. #include <utility>
  2.  
  3. template< typename F, typename ...types >
  4. struct reverter;
  5.  
  6. template< typename F >
  7. struct reverter< F >
  8. {
  9.    
  10.     template< typename ...types >
  11.     static
  12.     constexpr
  13.     decltype(auto)
  14.     apply(F && _f, types &&... _values)
  15.     {
  16.         return std::forward< F >(_f)(std::forward< types >(_values)...);
  17.     }
  18.    
  19. };
  20.  
  21. template< typename F, typename first, typename ...rest >
  22. struct reverter< F, first, rest... >
  23.     : reverter< F, rest... >
  24. {
  25.    
  26.     template< typename ...types >
  27.     static
  28.     constexpr
  29.     decltype(auto)
  30.     apply(F && _f, first && _first, rest &&... _rest, types &&... _values)
  31.     {
  32.         return reverter< F, rest... >::apply(std::forward< F >(_f), std::forward< rest >(_rest)..., std::forward< first >(_first), std::forward< types >(_values)...);
  33.     }
  34.    
  35. };
  36.  
  37. template< typename F, typename ...types >
  38. constexpr
  39. decltype(auto)
  40. revert(F && _f, types &&... _values)
  41. {
  42.     return reverter< F, types... >::apply(std::forward< F >(_f), std::forward< types >(_values)...);
  43. }
  44.  
  45. template< typename value_type, std::size_t ...extents >
  46. struct multiarray;
  47.  
  48. template< typename array_type >
  49. struct multiarray< array_type >
  50. {
  51.    
  52.     using type = array_type;
  53.    
  54. };
  55.  
  56. template< typename type, std::size_t first, std::size_t ...rest >
  57. struct multiarray< type, first, rest... >
  58.     : multiarray< type[first], rest... >
  59. {
  60.    
  61.     using value_type = type;
  62.    
  63. };
  64.  
  65. template< typename value_type, std::size_t ...extents >
  66. using multiarray_t = typename multiarray< value_type, extents... >::type;
  67.  
  68. template< typename array_type >
  69. struct subscripter
  70. {
  71.    
  72.     constexpr
  73.     subscripter(array_type & _array)
  74.         : array_(_array)
  75.     { ; }
  76.    
  77.     constexpr
  78.     array_type &
  79.     operator () () const
  80.     {
  81.         return array_;
  82.     }
  83.    
  84.     template< typename first, typename ...rest >
  85.     constexpr
  86.     decltype(auto)
  87.     operator () (first && _first, rest &&... _rest) const
  88.     {
  89.         return operator () (std::forward< rest >(_rest)...)[std::forward< first >(_first)];
  90.     }
  91.    
  92. private :
  93.    
  94.     array_type & array_;
  95.    
  96. };
  97.  
  98. template< typename array_type, typename ...indices >
  99. constexpr
  100. decltype(auto)
  101. subscript(array_type & _array, indices &&... _indices)
  102. {
  103.     return revert(subscripter< array_type >(_array), std::forward< indices >(_indices)...);
  104. }
  105.  
  106. template< std::size_t ...sizes >
  107. struct multicheck;
  108.  
  109. template<>
  110. struct multicheck<>
  111. {
  112.    
  113.     template< typename F, std::size_t ...indices >
  114.     static
  115.     constexpr
  116.     decltype(auto)
  117.     all_of(F && _f)
  118.     {
  119.         return std::forward< F >(_f)(std::index_sequence< indices... >{});
  120.     }
  121.    
  122.     template< typename F, std::size_t ...indices >
  123.     static
  124.     constexpr
  125.     decltype(auto)
  126.     any_of(F && _f)
  127.     {
  128.         return std::forward< F >(_f)(std::index_sequence< indices... >{});
  129.     }
  130.    
  131.     template< typename F, std::size_t ...indices >
  132.     static
  133.     constexpr
  134.     decltype(auto)
  135.     none_of(F && _f)
  136.     {
  137.         return std::forward< F >(_f)(std::index_sequence< indices... >{});
  138.     }
  139.    
  140. };
  141.  
  142. template< std::size_t first, std::size_t ...rest >
  143. struct multicheck< first, rest... >
  144.     : multicheck< rest... >
  145. {
  146.    
  147.     using base = multicheck< rest... >;
  148.    
  149.     template< typename F, std::size_t ...indices >
  150.     static
  151.     constexpr
  152.     decltype(auto)
  153.     all_of(F && _f)
  154.     {
  155.         return all_of< F, indices... >(std::forward< F >(_f), std::make_index_sequence< first >{});
  156.     }
  157.    
  158.     template< typename F, std::size_t ...indices >
  159.     static
  160.     constexpr
  161.     decltype(auto)
  162.     any_of(F && _f)
  163.     {
  164.         return any_of< F, indices... >(std::forward< F >(_f), std::make_index_sequence< first >{});
  165.     }
  166.    
  167.     template< typename F, std::size_t ...indices >
  168.     static
  169.     constexpr
  170.     decltype(auto)
  171.     none_of(F && _f)
  172.     {
  173.         return none_of< F, indices... >(std::forward< F >(_f), std::make_index_sequence< first >{});
  174.     }
  175.    
  176. private :
  177.  
  178.     template< typename F, std::size_t ...head, std::size_t ...tail >
  179.     static
  180.     constexpr
  181.     decltype(auto)
  182.     all_of(F && _f, std::index_sequence< tail... >)
  183.     {
  184.         return (base::template all_of< F, head..., tail >(std::forward< F >(_f)) && ...);
  185.     }
  186.  
  187.     template< typename F, std::size_t ...head, std::size_t ...tail >
  188.     static
  189.     constexpr
  190.     decltype(auto)
  191.     any_of(F && _f, std::index_sequence< tail... >)
  192.     {
  193.         return (base::template any_of< F, head..., tail >(std::forward< F >(_f)) || ...);
  194.     }
  195.  
  196.     template< typename F, std::size_t ...head, std::size_t ...tail >
  197.     static
  198.     constexpr
  199.     decltype(auto)
  200.     none_of(F && _f, std::index_sequence< tail... >)
  201.     {
  202.         return (!base::template none_of< F, head..., tail >(std::forward< F >(_f)) && ...);
  203.     }
  204.    
  205. };
  206.  
  207. #include <iostream>
  208. #include <type_traits>
  209.  
  210. #include <cassert>
  211. #include <cstdlib>
  212.  
  213. struct print
  214. {
  215.    
  216.     template< typename ...types >
  217.     decltype(auto)
  218.     operator () (types &&... _values) const
  219.     {
  220.         return (std::cout << ... << std::forward< types >(_values)) << std::endl;
  221.     }
  222.    
  223. };
  224.  
  225. template< typename array_type >
  226. struct print_array
  227. {
  228.    
  229.     constexpr
  230.     print_array(array_type & _array)
  231.         : array_(_array)
  232.     { ; }
  233.    
  234.     template< std::size_t ...indices >
  235.     bool
  236.     operator () (std::index_sequence< indices... >) const
  237.     {
  238.         return operator () (indices...);
  239.     }
  240.  
  241.     template< typename ...types >
  242.     bool
  243.     operator () (types &&... _values) const
  244.     {
  245.         std::cout << subscript(array_, std::forward< types >(_values)...) << ' ';
  246.         return true;
  247.     }
  248.    
  249. private :
  250.  
  251.     array_type & array_;
  252.    
  253. };
  254.  
  255. template< typename array_type >
  256. struct iota_array
  257. {
  258.    
  259.     constexpr
  260.     iota_array(array_type & _array)
  261.         : array_(_array)
  262.     { ; }
  263.    
  264.     template< std::size_t ...indices >
  265.     bool
  266.     operator () (std::index_sequence< indices... >) const
  267.     {
  268.         return operator () (indices...);
  269.     }
  270.  
  271.     template< typename ...types >
  272.     bool
  273.     operator () (types &&... _values) const
  274.     {
  275.         subscript(array_, std::forward< types >(_values)...) = i;
  276.         ++i;
  277.         return true;
  278.     }
  279.    
  280. private :
  281.  
  282.     mutable std::size_t i = 0;
  283.     array_type & array_;
  284.    
  285. };
  286.  
  287. template< typename type, std::size_t ...indices >
  288. struct invert_indices;
  289.  
  290. template< std::size_t ...counter, std::size_t ...indices >
  291. struct invert_indices< std::index_sequence< counter... >, indices... >
  292. {
  293.    
  294.     static constexpr std::size_t index[sizeof...(counter)] = {indices...};
  295.  
  296.     using type = std::index_sequence< index[sizeof...(indices) - 1 - counter]... >;
  297.    
  298. };
  299.  
  300. template< std::size_t ...indices >
  301. using make_inverted_indices_t = typename invert_indices< std::make_index_sequence< sizeof...(indices) >, indices... >::type;
  302.  
  303. using L = make_inverted_indices_t< 10, 20, 30 >;
  304. using R = std::index_sequence< 30, 20, 10 >;
  305. static_assert(std::is_same< L, R >{});
  306. static_assert(std::is_assignable< L &, R >{});
  307. static_assert(!std::is_assignable< L &, int >{});
  308.  
  309. constexpr
  310. bool
  311. test()
  312. {
  313.     using M = multiarray_t< char, 3, 3, 3 >;
  314.     M m{};
  315.     subscript(m, 2, 1, 0) = 0;
  316.     if (m[2][1][0] != 0) {
  317.         return false;
  318.     }
  319.     m[2][1][0] = 1;
  320.     if (subscript(m, 2, 1, 0) != 1) {
  321.         return false;
  322.     }
  323.     subscript(m, 2, 1)[0] = 2;
  324.     if (m[2][1][0] != 2) {
  325.         return false;
  326.     }
  327.     m[2][1][0] = 3;
  328.     if (subscript(m, 2)[1][0] != 3) {
  329.         return false;
  330.     }
  331.     subscript(m, 2)[1][0] = 4;
  332.     if (m[2][1][0] != 4) {
  333.         return false;
  334.     }    
  335.     m[2][1][0] = 5;
  336.     if (subscript(m)[2][1][0] != 5) {
  337.         return false;
  338.     }
  339.     return true;
  340. }
  341.  
  342. static_assert(test());
  343.  
  344. int
  345. main()
  346. {
  347.     revert(print{}, 1, ' ', 2, ' ', 3);
  348.     using M = multiarray_t< int, 3, 3, 3 >;
  349.     M m;
  350.     static_assert(std::is_same< M, int[3][3][3] >{});
  351.     multicheck< 3, 3, 3 >::all_of(print_array< M >(m));
  352.     std::cout << std::endl;
  353.     multicheck< 3, 3, 3 >::all_of(iota_array< M >(m));
  354.     multicheck< 3, 3, 3 >::all_of(print_array< M >(m));
  355.     std::cout << std::endl;
  356.     return EXIT_SUCCESS;
  357. }
Advertisement
Add Comment
Please, Sign In to add comment