角度のstrong typedefは今まで、tagged_real
のサンプルコードとして提供していましたが、たまに使うのでライブラリ化しました。
例:
#include <iostream>
#include <shand/angle.hpp>
int main()
{
shand::degree_f deg(45.0f);
shand::radian_f rad = shand::angle_cast<shand::radian_f>(deg);
std::cout << rad.get() << std::endl;
shand::radian_f sin_result = shand::sin(rad);
std::cout << sin_result.get() << std::endl;
}
出力:
0.785398
0.707107
角度の単位を変換するには、angle_cast()
関数テンプレートを使用します。Chronoライブラリではミリ秒や秒といった単位間の変換を型昇格として表現していますが、ディグリーとラジアンの間には昇格の関係はないと判断し、関数を通して変換することにしました。
ディグリー(度数法)とラジアン(弧度法)の角度型は、以下のように定義しています:
namespace shand {
struct degree_tag {};
struct radian_tag {};
template <class FloatingPoint>
using degree_t = shand::tagged_real<FloatingPoint, degree_tag>;
using degree_f = degree_t<float>;
using degree_d = degree_t<double>;
using degree_ld = degree_t<long double>;
template <class FloatingPoint>
using radian_t = shand::tagged_real<FloatingPoint, radian_tag>;
using radian_f = radian_t<float>;
using radian_d = radian_t<double>;
using radian_ld = radian_t<long double>;
}
degree_t
とradian_t
が、浮動小数点数型をパラメータにとる、tagged_real
のエイリアステンプレートで、_f
、_d
、_ld
が付いているものが、浮動小数点数型を設定済みのエイリアスになります。
その他、<cmath>
ヘッダで定義されている、いくつかの数学関数で、ラジアンを受け取ったり返したりする必要のあるものは、ラップして強い型付けにしています。
namespace shand {
template <class FloatingPoint>
radian_t<FloatingPoint> sin(const radian_t<FloatingPoint>& x)
{
return radian_t<FloatingPoint>(std::sin(x.get()));
}
...
template <class FloatingPoint>
radian_t<FloatingPoint> atan2(const FloatingPoint& y,
const FloatingPoint& x)
{
return radian_t<FloatingPoint>(std::atan2(y, x));
}
}