Garciat
2/26/2013 - 10:19 PM

leonardo_numbers.cpp

#include <type_traits>
#include <array>
#include <climits>
#include <iostream>
#include <algorithm>
#include <tuple>

template<size_t... Vals>
struct Sequence { };

template<typename Seq>
struct SequenceArray;

template<size_t... Vals>
struct SequenceArray<Sequence<Vals...>> {
	static const std::array<size_t, sizeof...(Vals)> arr;
};

template<typename Seq1, typename Seq2>
struct Concat;

template<size_t... Vals1, size_t... Vals2>
struct Concat<Sequence<Vals1...>, Sequence<Vals2...>> {
    typedef Sequence<Vals1..., Vals2...> type;
};

template<size_t I>
struct LeonardoNumber
	: std::integral_constant<size_t, LeonardoNumber<I - 2>::value + LeonardoNumber<I - 1>::value + 1> { };

template<>
struct LeonardoNumber<0>
	: std::integral_constant<size_t, 1> { };

template<>
struct LeonardoNumber<1>
	: std::integral_constant<size_t, 1> { };

template<size_t... Vals>
const std::array<size_t, sizeof...(Vals)> SequenceArray<Sequence<Vals...>>::arr = { { Vals... } };

template<size_t I = 2, bool Go = true>
struct MaxLeonardoSequenceHelper;

template<size_t I>
struct MaxLeonardoSequenceHelper<I, true> {
	static const size_t Next = LeonardoNumber<I>::value;

	// If the last Leonardo Number's size exceeds MAX(size_t)/2, then we have
	// found the last LN in the sequence below MAX(size_t). Stop!
	static const bool Go = LeonardoNumber<I - 1>::value < (size_t() - 1)/2;

	typedef typename Concat<Sequence<Next>, typename MaxLeonardoSequenceHelper<I + 1, Go>::type>::type type;
};

template<size_t I>
struct MaxLeonardoSequenceHelper<I, false> {
	typedef Sequence<> type;
};

struct MaxLeonardoSequence {
	typedef Concat<Sequence<1, 1>, MaxLeonardoSequenceHelper<>::type>::type type;
};

int main() {
	using namespace std;

	typedef SequenceArray<MaxLeonardoSequence::type> Leos;

	for (const auto &e : Leos::arr) {
		cout << e << endl;
	}
}