Rokiのチラ裏

学生による学習のログ

fizzbuzzタプル

fizz型、buzz型、fizzbuzz型を作り、fizzbuzz問題の規則に準じたタプル型を、コンパイル時に生成しなさい」という問題を出して見たので、その解答コードを以下に示す。

C++では単純なコンパイルfizzbuzzとvariadic templateに対する少しの操作が出来れば書けるので、そこまで難しくはないと思われる。

#include<type_traits>
#include<iostream>
#include<tuple>
#include<boost/type_index.hpp>
#include<srook/mpl/variadic_player.hpp>

struct FizzBuzz{};
struct Buzz{};
struct Fizz{
    constexpr FizzBuzz operator*(const Buzz&)const noexcept{return FizzBuzz{};} 
};

template<std::size_t v>
struct fizzbuzz_sequence_impl{
    using inner_result=srook::mpl::Concat_t<
                            typename std::conditional<
                                    (v%15==0),
                                        decltype(Fizz()*Buzz()),
                                        typename std::conditional<
                                            (v%3==0),
                                                Fizz,
                                                typename std::conditional<
                                                    (v%5==0),
                                                        Buzz,
                                                        std::integral_constant<std::size_t,v>
                                                >::type
                                        >::type
                                    >::type,
                            typename fizzbuzz_sequence_impl<v-1>::inner_result
                        >;
};
template<>
struct fizzbuzz_sequence_impl<0>{
    using inner_result=srook::mpl::pack<>;
};
template<template<class...>class Tuple,std::size_t v>
using fizzbuzz_sequence_t=srook::mpl::Transfer_t<Tuple,srook::mpl::Reverse_t<typename fizzbuzz_sequence_impl<v>::inner_result>>;

int main()
{
    using namespace boost::typeindex;
    std::cout<< type_id< fizzbuzz_sequence_t<std::tuple,100> >().pretty_name() <<std::endl;
}
std::__1::tuple<std::__1::integral_constant<unsigned long, 1ul>, std::__1::integral_constant<unsigned long, 2ul>, Fizz, std::__1::integral_constant<unsigned long, 4ul>, Buzz, Fizz, std::__1::integral_constant<unsigned long, 7ul>, std::__1::integral_constant<unsigned long, 8ul>, Fizz, Buzz, std::__1::integral_constant<unsigned long, 11ul>, Fizz, std::__1::integral_constant<unsigned long, 13ul>, std::__1::integral_constant<unsigned long, 14ul>, FizzBuzz, std::__1::integral_constant<unsigned long, 16ul>, std::__1::integral_constant<unsigned long, 17ul>, Fizz, std::__1::integral_constant<unsigned long, 19ul>, Buzz, Fizz, std::__1::integral_constant<unsigned long, 22ul>, std::__1::integral_constant<unsigned long, 23ul>, Fizz, Buzz, std::__1::integral_constant<unsigned long, 26ul>, Fizz, std::__1::integral_constant<unsigned long, 28ul>, std::__1::integral_constant<unsigned long, 29ul>, FizzBuzz, std::__1::integral_constant<unsigned long, 31ul>, std::__1::integral_constant<unsigned long, 32ul>, Fizz, std::__1::integral_constant<unsigned long, 34ul>, Buzz, Fizz, std::__1::integral_constant<unsigned long, 37ul>, std::__1::integral_constant<unsigned long, 38ul>, Fizz, Buzz, std::__1::integral_constant<unsigned long, 41ul>, Fizz, std::__1::integral_constant<unsigned long, 43ul>, std::__1::integral_constant<unsigned long, 44ul>, FizzBuzz, std::__1::integral_constant<unsigned long, 46ul>, std::__1::integral_constant<unsigned long, 47ul>, Fizz, std::__1::integral_constant<unsigned long, 49ul>, Buzz, Fizz, std::__1::integral_constant<unsigned long, 52ul>, std::__1::integral_constant<unsigned long, 53ul>, Fizz, Buzz, std::__1::integral_constant<unsigned long, 56ul>, Fizz, std::__1::integral_constant<unsigned long, 58ul>, std::__1::integral_constant<unsigned long, 59ul>, FizzBuzz, std::__1::integral_constant<unsigned long, 61ul>, std::__1::integral_constant<unsigned long, 62ul>, Fizz, std::__1::integral_constant<unsigned long, 64ul>, Buzz, Fizz, std::__1::integral_constant<unsigned long, 67ul>, std::__1::integral_constant<unsigned long, 68ul>, Fizz, Buzz, std::__1::integral_constant<unsigned long, 71ul>, Fizz, std::__1::integral_constant<unsigned long, 73ul>, std::__1::integral_constant<unsigned long, 74ul>, FizzBuzz, std::__1::integral_constant<unsigned long, 76ul>, std::__1::integral_constant<unsigned long, 77ul>, Fizz, std::__1::integral_constant<unsigned long, 79ul>, Buzz, Fizz, std::__1::integral_constant<unsigned long, 82ul>, std::__1::integral_constant<unsigned long, 83ul>, Fizz, Buzz, std::__1::integral_constant<unsigned long, 86ul>, Fizz, std::__1::integral_constant<unsigned long, 88ul>, std::__1::integral_constant<unsigned long, 89ul>, FizzBuzz, std::__1::integral_constant<unsigned long, 91ul>, std::__1::integral_constant<unsigned long, 92ul>, Fizz, std::__1::integral_constant<unsigned long, 94ul>, Buzz, Fizz, std::__1::integral_constant<unsigned long, 97ul>, std::__1::integral_constant<unsigned long, 98ul>, Fizz, Buzz>

このコードでは私のオレオレライブラリを使っている。しかしやっている事自体は、パックをリバースするのと、そのパックをタプルに適用する事だけである。一応、リバースとタプルへの適用のソースコードをライブラリから抽出して載せておく。