魔導書に触発されてRadian⇔Degree変換をやってみた

主に56ページ辺りに触発されて。

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

namespace std{
    template<int N, int D = 1>
    class ratio{
    public:
        static const int num = N;
        static const int den = D;
    };
}


template<
    typename ratio1,
    typename raito2,
    typename value_t = float
>
struct angle{
    
    angle() : value_(0.0f){}
    angle(value_t src) : value_(src){}

    template<
        typename r1, typename r2, typename value_t
    >
    angle(const angle<r1, r2, value_t>& src){
        transform(src.value());
    }
    
    value_t value() const{
        return value_;
    }
private:
    float value_;
    
    // 他の角度をテンプレート引数に設定された値で変換を行う
    // value = src * ratio1 / ratio2
    void transform(value_t src){
        value_  = src
                * (static_cast<value_t>(ratio1::num) / static_cast<value_t>(ratio1::den))
                / (static_cast<value_t>(raito2::num) / static_cast<value_t>(raito2::den));
    }
};

typedef std::ratio<314159265, 100000000> PI;

typedef angle<std::ratio<180>, PI > degree;
typedef angle<PI, std::ratio<180> > radian;


void
disp(degree deg, radian rad){
    std::cout << "deg:" << deg.value() << "\n";
    std::cout << "rad:" << rad.value() << "\n";
}

int
main(){
    
    std::cout << "deg2rad\n";

    degree deg(30.0f);
    radian rad(deg);

    std::cout << "deg:" << deg.value() << "\n";
    std::cout << "rag:" << rad.value() << "\n";
    std::cout << "\n";

    deg = 60.0f;
    disp(deg, deg);
    std::cout << "\n";

    rad = 1.0f;
    disp(rad, rad);
    std::cout << "\n";

    rad = deg;
    // 華麗に誤差が出てるので偽になる…
//    assert(degree(rad).value() == deg.value());
    std::cout << degree(rad).value() << " == " << deg.value() << "\n";
    
    return 0;
}

誤差が出るのはご愛嬌。

テンプレート引数だと実数型を使えないのでパイをratioで定義して渡したりしてます。

久々にテンプレートすげーと思えるコードを書いた気がする。

raitoもそうだけどこのイディオム自体は結構いろんなところでつかそう。

ゲームだと単位が違うだけで意味が同じ値なんて沢山あるしねー。

あとは、計算部分が違うだけで殆ど同じになりそうな感じだからそこもテンプレートを使って動的に変更したい。