カウンタ 〜その3〜

続きです。
今回は、上下限値の処理。
前回やった加算処理は割愛。

#include <assert.h>

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

template<
    typename ValueType,
    typename MaxChecker = non_checker,
    typename MinChecker = non_checker
>
struct counter{
    
    typedef ValueType    value_t;

    typedef MaxChecker max_checker_t;
    typedef MinChecker min_checker_t;
    
    counter(const value_t& v)
        : value_(v){}

    const value_t& value() const{
        return value_;
    }
    void value(const value_t& src){
        value_ = src;
        max_checker(*this);
        min_checker(*this);
    }

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

private:
    value_t    value_;

    max_checker_t    max_checker;
    min_checker_t    min_checker;
    
};

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

template<
    int MaxValue
>
struct max_stopper{
    
    static const int value = MaxValue;

    template<typename ValueType, typename MaxChecker, typename MinChecker>
    void operator ()(counter<ValueType, MaxChecker, MinChecker>& cout){
        if( cout.value() > value ){
            cout.value(value);
        }
    }
};

template<
    int MinValue
>
struct min_stopper{
    
    static const int value = MinValue;

    template<typename ValueType, typename MaxChecker, typename MinChecker>
    void operator ()(counter<ValueType, MaxChecker, MinChecker>& cout){
        if( cout.value() < value ){
            cout.value(value);
        }
    }
};

typedef max_stopper<10>    max;
typedef min_stopper< 0>    min;
typedef counter<int, max, min>    my_counter;

int
main(){
    
    my_counter    count(0);
    
    for( int i = 0 ; i < 20 ; i++ ){
        count.add(1);
    }
    assert(count.value() == max::value);
    
    
    for( int i = 0 ; i < 20 ; i++ ){
        count.substract(1);
    }
    assert(count.value() == min::value);

    return 0;
}

値が増減する時にテンプレートで指定された関数オブジェクトで処理を行ってます。
定義するタイミングで変更時の理を決定する事ができるので割と柔軟性は高い…ハズ…。


特に処理の内容は気にする必要はないのでこんな事も出来ます。

#include <iostream>
#include <boost/lexical_cast.hpp>
#include <string>

// 3の倍数と3が付く数字の時だけあほになります。
struct aho{
    template<typename ValueType, typename MaxChecker, typename MinChecker>
    void operator ()(counter<ValueType, MaxChecker, MinChecker>& cout){
        if( (cout.value() % 3 == 0)
        ||  (boost::lexical_cast<std::string>(cout.value()).find('3') != std::string::npos) ){
            std::cout << "あほ!";
        }
        else{
            std::cout << cout.value();
        }
    }
};

int
main(){
    
    counter<int, aho>    aho_cout(0);
    for( int i = 0 ; i < 100 ; i++ ){
        aho_cout.add(1);
        std::cout << ", ";
    }

    return 0;
}

しかし、今思ったけど特に2つ渡す必要はない気がしてきた。
あとで試してみよう。