カウンタ 〜その4〜

一応、形にはなったのでうp。
基本的な使い方は以下の通り。

#include <assert.h>

#include "counter.hpp"
#include "counter_compare.hpp"

int
main(){
    
    // 増減値を設定したり、最大最小の設定が出来る基本的なカウンタ
    counter<int>    basic_counter(0);    // int 型の値をカウントするカウンタ
    basic_counter.set_increment(1);        // counter<T>::increment() した際に加算される値を設定
    basic_counter.set_decrement(1);        // counter<T>::decrement() した際に減算される値を設定
    basic_counter.get_max_checker().value(10);    // 最大の値
    basic_counter.get_min_checker().value(-10);    // 最小の値

    for( int i = 0 ; i < 20 ; i++ ){
        basic_counter.increment();
        assert( basic_counter <= 10 );
    }
    for( int i = 0 ; i < 20 ; i++ ){
        basic_counter.decrement();
        assert( basic_counter >= -10 );
    }

    // 最大、最小の制限がないカウンタ
    custom_counter<int, int, int, counters::through, counters::through>    unlimited_counter(0);
    unlimited_counter.set_increment(1);
    unlimited_counter.set_decrement(1);
    
    for( int i = 0 ; i < 10000 ; i++ ){
        assert(unlimited_counter == i);
        unlimited_counter.increment();
    }
    
    unlimited_counter.value(0);
    for( int i = 0 ; i > -10000 ; i-- ){
        assert(unlimited_counter == i);
        unlimited_counter.decrement();
    }

    // 加算だけ行い、上限があるカウンタ
    custom_counter<
        int,
        int,
        counters::empty,
        counters::max_stop<int>,
        counters::through
    > accelerator(0);
    accelerator.set_increment(2);
    accelerator.get_max_checker().value(50);

    for( int i = 0 ; i < 100 ; i++ ){
        accelerator.increment();
    }
    assert(accelerator == 50);

    return 0;
}

基本的には、counter を用いてカウンタの管理を行い、
用途に合わせて使い分けたければ、custom_counter を用いて、自前で定義する感じ。
増減時の処理やインクリメント値を全部テンプレートで定義するので引数が多いです。
色々とツッコミどころはあるけど大まかにやりたかった事が出来たのでそれなりに満足。
初期化しないとゴミが入っていたり、初期化が手間だったりするのでそこはなんとかしたいんだけども…。
コンストラクタで各値を渡せば解決しそうなんだけどもさて。

以下、ヘッダーの中身。
長いです。

// counter.hpp
#ifndef _COUNTER_H_
#define _COUNTER_H_

namespace counters{

namespace detail{
    
    struct non_checker{
        template<typename T>
        void operator ()(T&){}
    };

};        // namespace detail

struct empty{};

template<
    typename ValueType,
    typename IncrementType = empty,
    typename DecrementType = empty,
    typename MaxChecker = detail::non_checker,
    typename MinChecker = detail::non_checker
>
struct counter_impl{
    
    typedef ValueType    value_t;

    typedef IncrementType    increment_t;
    typedef DecrementType    decrement_t;

    typedef MaxChecker    max_checker_t;
    typedef MinChecker    min_checker_t;

    counter_impl(const value_t& v)
        : value_(v){}

    const value_t& value() const{
        return value_;
    }
    void value(const value_t& src){
        value_ = src;
        
        // max_checker_ 及び、min_checker_ から
        // counter::value(value_t) を呼び出した際の無限ループを防ぐため。
        static bool loop_check = false;
        if(loop_check == false){
            loop_check = true;
            
            max_checker_(*this);
            min_checker_(*this);

            loop_check = false;
        }
    }

    void add(const value_t& add_value){
        value(value_ + add_value);
    }
    void substract(const value_t& sub_value){
        value(value_ - sub_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_ );
    }

    const max_checker_t& get_max_checker() const{
        return max_checker_;
    }
    max_checker_t& get_max_checker(){
        return max_checker_;
    }

    const min_checker_t& get_min_checker() const{
        return min_checker_;
    }
    min_checker_t& get_min_checker(){
        return min_checker_;
    }
private:
    value_t    value_;

    increment_t    increment_;
    decrement_t    decrement_;

    max_checker_t    max_checker_;
    min_checker_t    min_checker_;
};

//-----------------------------------------------------------------------------

template<
    typename T,
    typename ComparePolicy
>
struct stopper{
    
    typedef T value_t;

    void value(const value_t& rhs){
        value_ = rhs;
    }
    template<typename T>
    void operator ()(T& counter){
        if( ComparePolicy::compare(counter, value_) ){
            counter.value(value_);
        }
    }
    
private:
    T    value_;
};

// compares
#define COMPARE(class_name, op)    \
struct class_name{                \
    template<typename T0, typename T1>        \
    static bool compare(const T0& lhs, const T1& rhs){    \
        return lhs op rhs;                                \
    }                                                    \
};                                                        \

COMPARE(equal,        ==)
COMPARE(not_equal,    !=)
COMPARE(greater,      > )
COMPARE(greater_qual, >=)
COMPARE(less,         < )
COMPARE(less_equal,   <=)

#undef COMPARE


template<typename T>
struct max_stop
    : public stopper<T, greater_qual>{};

template<typename T>
struct min_stop
    : public stopper<T, less_equal>{};

typedef detail::non_checker through;

//-----------------------------------------------------------------------------

template<typename T>
struct counter
    : public counter_impl<T, T, T, max_stop<T>, min_stop<T> >{
    
    typedef counter_impl<T, T, T, max_stop<T>, min_stop<T> > inheritance;

    counter(const T& value) : inheritance(value){}
};

template<
    typename ValueType,
    typename IncrementType = empty,
    typename DecrementType = empty,
    typename MaxChecker = detail::non_checker,
    typename MinChecker = detail::non_checker
>
struct custom_counter
    : public counter_impl<ValueType, IncrementType, IncrementType, MaxChecker, MinChecker>{
    
    typedef
        counter_impl<ValueType, IncrementType, IncrementType, MaxChecker, MinChecker>
    inheritance;

    custom_counter(const ValueType& value) : inheritance(value){}
};

}        // namespace counters

using counters::counter;
using counters::custom_counter;

#endif
// "counter_compare.hpp"

#ifndef _COUNTER_COMPARE_
#define _COUNTER_COMPARE_


namespace counters{

template<
    typename ValueType, typename IncrementType, typename DecrementType, typename MaxChecker, typename MinChecker
>
struct counter_impl;

}        // namespace counters

#define COUNTER_COMPARE(op)    \
template<                    \
    typename ValueType, typename IncrementType, typename DecrementType, typename MaxChecker, typename MinChecker    \
>                            \
bool operator op(const counters::counter_impl<ValueType, IncrementType, DecrementType, MaxChecker,MinChecker>& lhs, const ValueType& rhs){ \
    return lhs.value() op rhs;    \
}    \
template<                    \
    typename ValueType, typename IncrementType, typename DecrementType, typename MaxChecker, typename MinChecker    \
>                            \
bool operator op(const ValueType& lhs, const counters::counter_impl<ValueType, IncrementType, DecrementType, MaxChecker,MinChecker>& rhs){ \
    return lhs op rhs.value();    \
}    \

COUNTER_COMPARE(==);
COUNTER_COMPARE(!=);
COUNTER_COMPARE(>=);
COUNTER_COMPARE(>);
COUNTER_COMPARE(<=);
COUNTER_COMPARE(<);

#undef COUNTER_COMPARE


#endif

色々とごちゃごちゃしてるけど書いてる事はそんなに難しい事じゃないです。
しかし、見事にコメントがないコードだな。
あとマクロでヤクザな事やってるけど気にしない方向で。
こんな事も出来るんだねぇ…。