これがあなたが従うべきではないアプローチです。(注:この投稿は冗談ですが、私はこのアプローチに従わないことを真剣に考えています。C++の理解レベルでこのアプローチを理解しようとすることもお勧めできません。)
#include <iostream>
struct Fib
{
template<int n, int first=1, int second=1> struct Eval { enum {value = Eval<n-1, first, second>::value + Eval<n-2, first, second>::value}; };
template<int first, int second> struct Eval<1, first, second> { enum {value = second}; };
template<int first, int second> struct Eval<0, first, second> { enum {value = first}; };
};
struct SpecificFib
{
template<int n> struct Eval { enum{ value = Fib::template Eval<n, 1, 2>::value }; };
};
template<int... values> struct Sequence {};
template<typename Seq, int n> struct Append;
template<int... values, int n> struct Append<Sequence<values...>, n> { typedef Sequence<values...,n> type; };
template<typename Seq, int n> struct Prepend;
template<int... values, int n> struct Prepend<Sequence<values...>, n> { typedef Sequence<n, values...> type; };
template<typename Func,typename Seq,typename Test=void> struct Filter;
template<typename Func,int first, int... values>
struct Filter<Func,Sequence<first,values...>,typename std::enable_if< Func::template Eval<first>::value>::type>
{
typedef typename Prepend<typename Filter<Func,Sequence<values...>>::type,first>::type type;
};
template<typename Func,int first, int... values>
struct Filter<Func,Sequence<first,values...>,typename std::enable_if< !Func::template Eval<first>::value>::type>
{
typedef typename Filter<Func,Sequence<values...>>::type type;
};
template<typename Func> struct Filter<Func,Sequence<>> { typedef Sequence<> type; };
struct IsEven {
template<int n> struct Eval { enum{ value = !(n%2) }; };
};
template<typename Func,typename Seq> struct Map;
template<typename Func,int first, int... values>
struct Map<Func, Sequence<first,values...>>
{
typedef Sequence<values...> Tail;
typedef typename Map<Func,Tail>::type TailMapped;
enum { firstMapped = Func::template Eval<first>::value };
typedef typename Prepend<TailMapped,firstMapped>::type type;
};
template<typename Func>
struct Map<Func,Sequence<>>
{
typedef Sequence<> type;
};
template<int begin, int end>
struct generate_sequence
{
template<int current, int... values>
struct helper: helper<current-1, current-1, values...> {};
template<int... values>
struct helper<begin, values...>
{
typedef Sequence<values...> type;
};
typedef typename helper<end>::type type;
};
template<typename Seq> struct Sum;
template<int first, int... values> struct Sum<Sequence<first, values...>> { enum {value = first + Sum<Sequence<values...>>::value}; };
template<> struct Sum<Sequence<>> { enum {value = 0}; };
template<typename Seq1, typename Seq2=Sequence<>>
struct Reverse { typedef Seq2 type; };
template<int first, int... values, typename Seq2>
struct Reverse<Sequence<first,values...>, Seq2>:Reverse<Sequence<values...>, typename Prepend<Seq2,first>::type> {};
template<typename Seq, char sep=','> struct PrintHelper;
template<int first, int second, int... values, char sep> struct PrintHelper<Sequence<first,second,values...>, sep>:PrintHelper<Sequence<second,values...>, sep>
{
PrintHelper() { std::cout << sep << first; }
};
template<int last, char sep> struct PrintHelper<Sequence<last>, sep>:PrintHelper<Sequence<>, sep>
{
PrintHelper() { std::cout << last; }
};
template<char sep> struct PrintHelper<Sequence<>,sep> { PrintHelper() {} void Do() const {} };
template<typename Seq, char sep=','> struct Print: PrintHelper< typename Reverse<Seq>::type, sep >
{};
typedef typename generate_sequence<0, 10>::type ZeroTo9;
typedef typename Map<SpecificFib,ZeroTo9>::type First10Fibs;
typedef typename Filter<IsEven,First10Fibs>::type First10FibsThatAreEven;
template<typename Sequence>
void PrintSomeInfo( std::string const& name )
{
std::cout << name << " {";
Print<Sequence>();
std::cout << "} sums to " << Sum<Sequence>::value << "\n";
}
int main()
{
PrintSomeInfo<ZeroTo9>("Zero to 9");
PrintSomeInfo<First10Fibs>("First 10 fibs");
PrintSomeInfo<First10FibsThatAreEven>("First 10 fibs that are even");
}
それがお役に立てば幸いです。
私が上でやっていることは、テンプレートプログラミングで遊んでいることです。私は、コンパイラが適切にコンパイルされた場合Sum<Sequence>::value
、それが単一のコンパイル時の値になるように、かなり強力なC++型システムを使用して答えを推測しています。
技術的には、これはC++で書かれた質問に対する答えです。ボーナスとして、O(1)
実行時間があります。:)
..。
もっと真剣に。一度に1ステップずつ問題を解決する必要があります。
シーケンスの最初の10個の要素を出力するプログラムを作成します。私は「上記のように」と言いますが、あなたはあなたが理解する方法でそれをするべきです。