Project Euler 1(3)

cGeneratorクラスを作って、next()で値を返すクラスはこれを継承することにする。

template<typename T>
class cGenerator {
public:
    virtual ~cGenerator() { }
    virtual T next() = 0;
};

本当はポインタなんか使いたくない。いちいちdeleteしなければならないのが嫌。だから即行でdeleteする。問題ありならあとで考える。

#include <iostream>

using namespace std;

const int   N = 1000;

template<typename T>
class cGenerator {
public:
    virtual ~cGenerator() { }
    virtual T next() = 0;
};

template<typename T = int>
class range : public cGenerator<T> {
    T   current;
    T   end;
    T   delta;
    
public:
    range(T b, T e, T d = 1) : current(b), end(e), delta(d) { }
    range(T e) : end(e) {
        current = 0;
        delta = d;
    }
    range() {
        current = end = delta = 0;
    }
    ~range() { }
    
    T next() {
        if(current < end) {
            T   v = current;
            current += 1;
            return v;
        }
        else {
            throw(1);
        }
    }
};

template<typename T>
class filter : public cGenerator<T>{
    bool (* pred)(T);
    cGenerator<T>   *obj;
    
public:
    filter(bool (* p)(T), cGenerator<T> *o) : pred(p), obj(o) { }
    ~filter() {
        delete obj;
    }
    T next() {
        T   v;
        do {
            v = obj->next();
        } while(!pred(v));
        return v;
    }
};

template<typename T>
T sum(cGenerator<T> *o) {
    T   s = 0;
    try {
        while(true) {
            s += o->next();
        }
    }
    catch(int e) {
        delete o;
        return s;
    }
};

bool div35(int n) { return n % 3 == 0 || n % 5 == 0; }

int main() {
    cout << sum(new filter<int>(div35, new range<>(1, N))) << endl;
}

newとあとやっぱり型指定しなければならないのがみっともないが。