カウンタ 〜その2〜

この前の続きです。

#include <iostream>
#include <assert.h>


template<
    typename ValueType
>
struct counter_impl{
    
    typedef ValueType    value_t;
    
    counter_impl(const value_t& v)
        : value_(v){}
    
    const value_t& value() const{
        return value_;
    }
    void value(const value_t& src){
        value_ = src;
    }

    void add(const value_t& add_value){
        value_ += add_value;
    }
    void substract(const value_t& sub_value){
        value_ -= sub_value;
    }

private:
    value_t    value_;
};


template<
    typename ValueType,
    typename IncrementType = ValueType,
    typename DecrementType = IncrementType
>
struct counter
    : public  counter_impl<ValueType>{
    
    typedef ValueType    value_t;
    typedef counter_impl<ValueType>    counter_t;

    typedef IncrementType    increment_t;
    typedef DecrementType    decrement_t;

    counter(const value_t& value)
        : counter_t(value){}

    void set_increment(const increment_t& src){
        increment_ = src;
    };
    void increment(){
        add( increment_ );
    }
    
    void set_decrement(const decrement_t& src){
        decrement_ = src;
    };
    void decrement(){
        substract( decrement_ );
    }

private:
    increment_t    increment_;
    decrement_t    decrement_;
};

struct non_increment{};

typedef counter<int>    my_counter;

int
main(){
    
    my_counter    count1(0);
    count1.set_increment(2);
    count1.set_decrement(1);

    int    count2 = 0;

    for( int i = 0 ; i < 10 ; i++ ){
        count1.increment();
        count2 += 2;
        assert(count1.value() == count2 );
    }
    
    for( int i = 0 ; i < 10 ; i++ ){
        count1.decrement();
        count2 -= 1;
        assert(count1.value() == count2 );
    }

    return 0;
}

とりあえず、増減処理だけ実装してみた。
色々と考えた挙句に結局、最初に戻ってきた感じがする…。
non_increment は増減処理をしない場合にテンプレートに突っ込む

typedef counter<int, non_increment>    non_increment_counter;
assert(sizeof(non_increment_counter) == 8);

こんな感じ。
ただ、この場合、counter がインスタンスとして、non_incrementer を保持してるんで
空のクラスでも1バイト食っちゃうんだよねぇ…。
本当はここをどうにかして無くしたかったんで、多重継承とか色々試してみたんだけども
コードの可読性が落ちる+ダイヤモンド継承の問題があったので結局、今の形になりました。

template<
    typename ValueType,
    typename Incrementer,
    typename Decrementer
>
struct counter
    : public  counter_impl<ValueType>
    , private Incrementer,
    , private Decrementer{
};
counter<int, non_increment, non_increment>    // 同クラスを2回継承してる

あと counter のテンプレート引数の数をどうにかしたい。
個人的にテンプレート引数が多いととっつき難い感じがするんだけどどうなんだろう。
この後も、上限処理をするクラスとかを引数にとるからまだ増える予定。