Advertisement
Guest User

Untitled

a guest
Mar 12th, 2017
620
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 8.17 KB | None | 0 0
  1. #include <cstddef>
  2. #include <type_traits>
  3. #include <utility>
  4. #include <ostream>
  5.  
  6. namespace fizzbuzz {
  7.     template< typename... T >
  8.     struct typelist {
  9.         static constexpr std::size_t size = sizeof...( T );
  10.     };
  11.  
  12.     namespace detail {
  13.         template< typename... T >
  14.         struct concat_impl {
  15.         };
  16.         template<>
  17.         struct concat_impl<> {
  18.             using t = typelist<>;
  19.         };
  20.         template< typename... head, typename... tail >
  21.         struct concat_impl< typelist< head... >, typelist< tail... > > {
  22.             using t = typelist< head..., tail... >;
  23.         };
  24.         template< typename... head, typename... tail >
  25.         struct concat_impl< typelist< head... >, tail... > {
  26.             using t = typename concat_impl< typelist< head... >, typename concat_impl< tail... >::t >::t;
  27.         };
  28.         template< typename head, typename... tail >
  29.         struct concat_impl< head, tail... > {
  30.             using t = typename concat_impl< typelist< head >, tail... >::t;
  31.         };
  32.     }
  33.     template< typename... T >
  34.     using concat = typename detail::concat_impl< T... >::t;
  35.  
  36.     template< char c >
  37.     struct char_ {
  38.         static constexpr auto v = c;
  39.     };
  40.     template< int i >
  41.     struct int_ {
  42.         static constexpr auto v = i;
  43.     };
  44.  
  45.     namespace detail {
  46.         template< typename list >
  47.         struct discard_trailing_zeroes {
  48.         };
  49.         template< typename head, typename... tail >
  50.         struct discard_trailing_zeroes< typelist< head, tail... > > {
  51.             using t = concat< head, typename discard_trailing_zeroes< typelist< tail... > >::t >;
  52.         };
  53.         template< typename... tail >
  54.         struct discard_trailing_zeroes< typelist< char_< '\0' >, tail... > > {
  55.             using t = typelist<>;
  56.         };
  57.         template<>
  58.         struct discard_trailing_zeroes< typelist<> > {
  59.             using t = typelist<>;
  60.         };
  61.     }
  62. #define LITERAL2LIST_1( str, i )    \
  63.     ::fizzbuzz::char_< ( sizeof( str ) / sizeof( *str ) > ( i ) ? str[ ( i ) ] : '\0' ) >
  64. #define LITERAL2LIST_2( str, i )    \
  65.     LITERAL2LIST_1( str, i + 0 ),   \
  66.     LITERAL2LIST_1( str, i + 1 )
  67. #define LITERAL2LIST_4( str, i )    \
  68.     LITERAL2LIST_2( str, i + 0 ),   \
  69.     LITERAL2LIST_2( str, i + 2 )
  70. #define LITERAL2LIST_8( str, i )    \
  71.     LITERAL2LIST_4( str, i + 0 ),   \
  72.     LITERAL2LIST_4( str, i + 4 )
  73. #define LITERAL2LIST_16( str, i )   \
  74.     LITERAL2LIST_8( str, i + 0 ),   \
  75.     LITERAL2LIST_8( str, i + 8 )
  76. #define LITERAL2LIST( str ) std::enable_if_t< ( sizeof( str ) - 1 < 16 ), ::fizzbuzz::detail::discard_trailing_zeroes< ::fizzbuzz::typelist< LITERAL2LIST_16( str, 0 ) > >::t >
  77.  
  78.     inline std::ostream& operator<<( std::ostream& stream, typelist<> ) {
  79.         return stream;
  80.     }
  81.     template< char... c >
  82.     std::ostream& operator<<( std::ostream& stream, typelist< char_< c >... > ) {
  83.         constexpr char s[] = { c... };
  84.         return stream.write( s, sizeof( s ) / sizeof( *s ) );
  85.     }
  86.     template< int head, int... tail >
  87.     std::ostream& operator<<( std::ostream& stream, typelist< int_< head >, int_< tail >... > ) {
  88.         return stream << head << ' ' << typelist< int_< tail >... >{};
  89.     }
  90.     template< int head >
  91.     std::ostream& operator<<( std::ostream& stream, typelist< int_< head > > ) {
  92.         return stream << head;
  93.     }
  94.  
  95.     namespace detail {
  96.         template< std::size_t n, int a0, int d >
  97.         struct arithmetic_progression_impl {
  98.             using t = concat< typename arithmetic_progression_impl< n / 2, a0, d >::t, typename arithmetic_progression_impl< n - n / 2, a0 + n / 2 * d, d >::t >;
  99.         };
  100.         template< int d, int a0 >
  101.         struct arithmetic_progression_impl< 0, a0, d > {
  102.             using t = typelist<>;
  103.         };
  104.         template< int d, int a0 >
  105.         struct arithmetic_progression_impl< 1, a0, d > {
  106.             using t = typelist< int_< a0 > >;
  107.         };
  108.     }
  109.     template< std::size_t n, int a0 = 0, int d = 1 >
  110.     using arithmetic_progression = typename detail::arithmetic_progression_impl< n, a0, d >::t;
  111.  
  112.     namespace detail {
  113.         template< typename list, typename separator >
  114.         struct separate_impl {
  115.         };
  116.         template< typename head, typename... tail, typename separator >
  117.         struct separate_impl< typelist< head, tail... >, separator > {
  118.             using t = concat< head, separator, typename separate_impl< typelist< tail... >, separator >::t >;
  119.         };
  120.         template< typename head, typename separator >
  121.         struct separate_impl< typelist< head >, separator > {
  122.             using t = typelist< head >;
  123.         };
  124.     }
  125.     template< typename list, typename separator >
  126.     using separate = typename detail::separate_impl< list, separator >::t;
  127.  
  128.     namespace detail {
  129.         template< typename list, template< typename > class meta_functor >
  130.         struct transform_impl {
  131.         };
  132.         template< typename head, typename... tail, template< typename > class meta_functor >
  133.         struct transform_impl< typelist< head, tail... >, meta_functor > {
  134.             using t = concat< typename meta_functor< head >::t, typename transform_impl< typelist< tail... >, meta_functor >::t >;
  135.         };
  136.         template< template< typename > class meta_functor >
  137.         struct transform_impl< typelist<>, meta_functor > {
  138.             using t = typelist<>;
  139.         };
  140.     }
  141.     template< typename list, template< typename > class meta_functor >
  142.     using transform = typename detail::transform_impl< list, meta_functor >::t;
  143.  
  144.     namespace detail {
  145.         template< unsigned i >
  146.         struct log10_impl {
  147.             static constexpr int v = 1 + log10_impl< i / 10 >::v;
  148.         };
  149.         template<>
  150.         struct log10_impl< 0 > {
  151.             static constexpr int v = -1;
  152.         };
  153.     }
  154.     template< unsigned i >
  155.     static constexpr int log10 = detail::log10_impl< i >::v;
  156.  
  157.     namespace detail {
  158.         template< unsigned i >
  159.         struct pow10_impl {
  160.             static constexpr unsigned v = pow10_impl< i / 2 >::v * pow10_impl< i - i / 2 >::v;
  161.         };
  162.         template<>
  163.         struct pow10_impl< 1 > {
  164.             static constexpr unsigned v = 10;
  165.         };
  166.         template<>
  167.         struct pow10_impl< 0 > {
  168.             static constexpr unsigned v = 1;
  169.         };
  170.     }
  171.     template< unsigned i >
  172.     static constexpr unsigned pow10 = detail::pow10_impl< i >::v;
  173.  
  174.     namespace detail {
  175.         template< int i, typename = std::make_integer_sequence< int, 1 + log10< i > > >
  176.         struct int2str_impl_impl {
  177.         };
  178.         template< int i, int... indices >
  179.         struct int2str_impl_impl< i, std::integer_sequence< int, indices... > > {
  180.             using t = typelist< char_< '0' + i / pow10< sizeof...( indices ) - 1 - indices > % 10 >... >;
  181.         };
  182.  
  183.         template< int i, bool neg = ( i < 0 ) >
  184.         struct int2str_impl {
  185.             using t = concat< char_< '-' >, typename int2str_impl< -i >::t >;
  186.         };
  187.         template< int i >
  188.         struct int2str_impl< i, false > {
  189.             using t = typename int2str_impl_impl< i >::t;
  190.         };
  191.         template<>
  192.         struct int2str_impl< 0, false > {
  193.             using t = typelist< char_< '0' > >;
  194.         };
  195.     }
  196.     template< typename T >
  197.     struct int2str {
  198.         using t = T;
  199.     };
  200.     template< int i >
  201.     struct int2str< int_< i > > {
  202.         using t = typename detail::int2str_impl< i >::t;
  203.     };
  204.  
  205.     template< int i, typename T >
  206.     struct divisibility_replacement_rule {
  207.         static constexpr auto v = i;
  208.         using t = T;
  209.     };
  210.     template< typename ruleset >
  211.     struct divisibility_replacer {
  212.         template< int x, typename = ruleset >
  213.         struct match {
  214.         };
  215.         template< int x, typename head, int... i, typename... tail >
  216.         struct match< x, typelist< head, divisibility_replacement_rule< i, tail >... > > {
  217.             using tail_rec = match< x, typelist< divisibility_replacement_rule< i, tail >... > >;
  218.             static constexpr bool matched_here = ( x % head::v == 0 );
  219.             static constexpr bool matched = matched_here || tail_rec::matched;
  220.             using t_here = std::conditional_t< matched_here, typename head::t, typelist<> >;
  221.             using t = concat< t_here, typename tail_rec::t >;
  222.         };
  223.         template< int x >
  224.         struct match< x, typelist<> > {
  225.             static constexpr bool matched = false;
  226.             using t = typelist<>;
  227.         };
  228.  
  229.         template< typename U >
  230.         struct functor {
  231.             using t = U;
  232.         };
  233.         template< int x >
  234.         struct functor< int_< x > > {
  235.             using match_result = match< x >;
  236.             using t = std::conditional_t< match_result::matched, typename match_result::t, int_< x > >;
  237.         };
  238.     };
  239.  
  240.     struct fizzbuzz_replacer :
  241.         divisibility_replacer<
  242.             typelist<
  243.                 divisibility_replacement_rule< 3, LITERAL2LIST( "Fizz" ) >,
  244.                 divisibility_replacement_rule< 5, LITERAL2LIST( "Buzz" ) >
  245.             >
  246.         >
  247.     {
  248.     };
  249.  
  250.     template< int min = 1, int max = 100, typename = std::enable_if_t< ( min < max ) > >
  251.     using fizzbuzz = transform< transform< separate< arithmetic_progression< max - min + 1, min, 1 >, LITERAL2LIST( ", " ) >, fizzbuzz_replacer::functor >, int2str >;
  252. }
  253.  
  254. #include <iostream>
  255.  
  256. int main() {
  257.     std::cout << fizzbuzz::fizzbuzz<>{} << '\n';
  258. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement