Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <iostream>
- #include <string>
- #include <cstdlib>
- #include <boost/mpl/string.hpp>
- #include <boost/mpl/fold.hpp>
- #include <boost/mpl/size_t.hpp>
- using namespace std;
- using namespace boost;
- ///////////////////////////////////////////////////////////////////////////////
- // exponentiation calculations
- template <int accum, int base, int exp> struct POWER_CORE : POWER_CORE<accum * base, base, exp - 1>{};
- template <int accum, int base>
- struct POWER_CORE<accum, base, 0>
- {
- enum : int { val = accum };
- };
- template <int base, int exp> struct POWER : POWER_CORE<1, base, exp>{};
- ///////////////////////////////////////////////////////////////////////////////
- // # of digit calculations
- template <int depth, unsigned int i> struct NUM_DIGITS_CORE : NUM_DIGITS_CORE<depth + 1, i / 10>{};
- template <int depth>
- struct NUM_DIGITS_CORE<depth, 0>
- {
- enum : int { val = depth};
- };
- template <int i> struct NUM_DIGITS : NUM_DIGITS_CORE<0, i>{};
- template <>
- struct NUM_DIGITS<0>
- {
- enum : int { val = 1 };
- };
- ///////////////////////////////////////////////////////////////////////////////
- // Convert digit to character (1 -> '1')
- template <int i>
- struct DIGIT_TO_CHAR
- {
- enum : char{ val = i + 48 };
- };
- ///////////////////////////////////////////////////////////////////////////////
- // Find the digit at a given offset into a number of the form 0000000017
- template <unsigned int i, int place> // place -> [0 .. 10]
- struct DIGIT_AT
- {
- enum : char{ val = (i / POWER<10, place>::val) % 10 };
- };
- struct NULL_CHAR
- {
- enum : char{ val = '\0' };
- };
- ///////////////////////////////////////////////////////////////////////////////
- // Convert the digit at a given offset into a number of the form '0000000017' to a character
- template <unsigned int i, int place> // place -> [0 .. 9]
- struct ALT_CHAR : DIGIT_TO_CHAR< DIGIT_AT<i, place>::val >{};
- ///////////////////////////////////////////////////////////////////////////////
- // Convert the digit at a given offset into a number of the form '17' to a character
- // Template description, with specialization to generate null characters for out of range offsets
- template <unsigned int i, int offset, int numDigits, bool inRange>
- struct OFFSET_CHAR_CORE_CHECKED{};
- template <unsigned int i, int offset, int numDigits>
- struct OFFSET_CHAR_CORE_CHECKED<i, offset, numDigits, false> : NULL_CHAR{};
- template <unsigned int i, int offset, int numDigits>
- struct OFFSET_CHAR_CORE_CHECKED<i, offset, numDigits, true> : ALT_CHAR<i, (numDigits - offset) - 1 >{};
- // Perform the range check and pass it on
- template <unsigned int i, int offset, int numDigits>
- struct OFFSET_CHAR_CORE : OFFSET_CHAR_CORE_CHECKED<i, offset, numDigits, offset < numDigits>{};
- // Calc the number of digits and pass it on
- template <unsigned int i, int offset>
- struct OFFSET_CHAR : OFFSET_CHAR_CORE<i, offset, NUM_DIGITS<i>::val>{};
- ///////////////////////////////////////////////////////////////////////////////
- // Integer to char* template. Works on unsigned ints.
- template <unsigned int i>
- struct IntToStr
- {
- const static char str[];
- typedef typename mpl::string<
- OFFSET_CHAR<i, 0>::val,
- OFFSET_CHAR<i, 1>::val,
- OFFSET_CHAR<i, 2>::val,
- OFFSET_CHAR<i, 3>::val,
- OFFSET_CHAR<i, 4>::val,
- OFFSET_CHAR<i, 5>::val,
- /*OFFSET_CHAR<i, 6>::val,
- OFFSET_CHAR<i, 7>::val,
- OFFSET_CHAR<i, 8>::val,
- OFFSET_CHAR<i, 9>::val,*/
- NULL_CHAR::val>::type type;
- };
- template <unsigned int i>
- const char IntToStr<i>::str[] =
- {
- OFFSET_CHAR<i, 0>::val,
- OFFSET_CHAR<i, 1>::val,
- OFFSET_CHAR<i, 2>::val,
- OFFSET_CHAR<i, 3>::val,
- OFFSET_CHAR<i, 4>::val,
- OFFSET_CHAR<i, 5>::val,
- OFFSET_CHAR<i, 6>::val,
- OFFSET_CHAR<i, 7>::val,
- OFFSET_CHAR<i, 8>::val,
- OFFSET_CHAR<i, 9>::val,
- NULL_CHAR::val
- };
- template <bool condition, class Then, class Else>
- struct IF
- {
- typedef Then RET;
- };
- template <class Then, class Else>
- struct IF<false, Then, Else>
- {
- typedef Else RET;
- };
- template < typename Str1, typename Str2 >
- struct concat : mpl::insert_range<Str1, typename mpl::end<Str1>::type, Str2> {};
- template <typename Str1, typename Str2, typename Str3 >
- struct concat3 : mpl::insert_range<Str1, typename mpl::end<Str1>::type, typename concat<Str2, Str3 >::type > {};
- typedef typename mpl::string<'f','i','z','z'>::type fizz;
- typedef typename mpl::string<'b','u','z','z'>::type buzz;
- typedef typename mpl::string<'\r', '\n'>::type mpendl;
- typedef typename concat<fizz, buzz>::type fizzbuzz;
- // discovered boost mpl limitation on some length
- template <int N>
- struct FizzBuzz
- {
- typedef typename concat3<typename FizzBuzz<N - 1>::type, typename IF<N % 15 == 0, typename fizzbuzz::type, typename IF<N % 3 == 0, typename fizz::type, typename IF<N % 5 == 0, typename buzz::type, typename IntToStr<N>::type >::RET >::RET >::RET, typename mpendl::type>::type type;
- //typedef typename concat<typename FizzBuzz<N - 1>::type, typename IF<N % 15 == 0, typename fizzbuzz::type, typename IF<N % 3 == 0, typename fizz::type, typename IF<N % 5 == 0, typename buzz::type, typename IntToStr<N>::type >::RET >::RET >::RET>::type type;
- };
- template <>
- struct FizzBuzz<1>
- {
- typedef mpl::string<'1','\r','\n'>::type type;
- };
- int main(int argc, char** argv)
- {
- std::cout << mpl::c_str<FizzBuzz<8>::type>::value << std::endl;
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement