テンプレート引数がいちいちついて回るのは、クラスを関数で包めば回避できる。例えばmapなら、
template<typename T, typename U, typename V> class cMap { T& func; U& gen; public: cMap(T& f, U& g) : func(f), gen(g) { } V next() { return func(gen.next()); } }; template<typename T, typename U> auto map(T& func, U& gen) -> cMap<T,U,decltype(func(gen.next()))>{ return cMap<T,U,decltype(func(gen.next()))>(func, gen); }
これを次のように使う。
cout << sum(map([] (int n) { return n * 2; }, range<>(10))) << endl;
ラムダも使える。
最初、gen.next()の返り値の型Vをクラスのほうでひねり出そうとしたができなくて、これも関数に押し付けたらあっさり通った。
#include <iostream> using namespace std; template<typename T = int> class range { T current; T end; T delta; public: range(T b, T e, T d = 1) : current(b), end(e), delta(d) { } range(T e) : current(0), end(e), delta(1) { } range() : current(0), end(0), delta(0) { } T next() { if(current < end) { T v = current; current += delta; return v; } else { throw(1); } } }; template<typename T, typename U, typename V> class cFilter { T& pred; U& gen; public: cFilter(T& p, U& g) : pred(p), gen(g) { } V next() { V v; do v = gen.next(); while(!pred(v)); return v; } }; template<typename T, typename U> auto filter(T& pred, U& gen) -> cFilter<T,U,decltype(gen.next())>{ return cFilter<T,U,decltype(gen.next())>(pred, gen); } template<typename T> auto sum(T& gen) -> decltype(gen.next()) { decltype(gen.next()) s = 0; try { while(true) s += gen.next(); } catch(int e) { return s; } } int main() { const int N = 1000; cout << sum(filter([] (int n) { return n % 3 == 0 || n % 5 == 0; }, range<>(1, N))) << endl; }