boost::units を少し使いやすくする

boost::unitsを使う場合、下記のようになる。

#include <boost/untis/systems/si.hpp>
#include <boost/units/systems/prefixes.hpp>

using namespace boost::units;

quantity<si::time> x(1.0*si::second);		// 1 s
quantity<si::time> y(1.0*si::milli*si::meter);	// 0.001 s

この書き方にはいくつか気になる点がある。


まず、quantityで使ってる単位が分かりづらい。
この例だと、SI 単位系における時間の単位は秒だから、分かるといえば分かるけど、
もっと、単位が秒だということを主張してほしい。


さらに、秒以外の単位(ミリ秒、マイクロ秒、…)でも扱いたい。
浮動小数点の誤差などを考えると特に。


いちいち接頭辞を掛けるのがめんどくさい。
millisecond、microsecond、nanosecond、millimeter、centimeter、kilometer くらいは
デフォルトで用意しておいてくれてもいいはず。


というわけで、これらの不満を無理やり解決してみた。

#include <boost/units/systems/si.hpp>
#include <boost/units/make_scaled_unit.hpp>

// 実際は適当な名前空間に放り込んだ方がいいのかもしれない
typedef boost::units::si::time second;
using boost::units::si::seconds;

typedef boost::units::make_scaled_unit<
		second, boost::units::scale<10, boost::units::static_rational<-3> >
	>::type millisecond;
BOOST_UNITS_STATIC_CONSTANT(milliseconds, millisecond);

typedef boost::units::make_scaled_unit<
		second, boost::units::scale<10, boost::units::static_rational<-6> >
	>::type microsecond;
BOOST_UNITS_STATIC_CONSTANT(microseconds, microsecond);

typedef boost::units::make_scaled_unit<
		second, boost::units::scale<10, boost::units::static_rational<-9> >
	>::type nanosecond;
BOOST_UNITS_STATIC_CONSTANT(nanoseconds, nanosecond);

typedef boost::units::si::length meter;
using boost::units::si::meters;

typedef boost::units::make_scaled_unit<
		meter, boost::units::scale<10, boost::units::static_rational<-3> >
	>::type millimeter;
BOOST_UNITS_STATIC_CONSTANT(millimeters, millimeter);

typedef boost::units::make_scaled_unit<
		meter, boost::units::scale<10, boost::units::static_rational<-2> >
	>::type centimeter;
BOOST_UNITS_STATIC_CONSTANT(centimeters, centimeter);

typedef boost::units::make_scaled_unit<
		meter, boost::units::scale<10, boost::units::static_rational<3> >
	>::type kilometer;
BOOST_UNITS_STATIC_CONSTANT(kilometers, kilometer);

とりあえず秒とメートルだけ定義してみた。

#include <iostream>

int main()
{
	using boost::units::quantity;

	std::cout << quantity<second>(1*seconds) << std::endl;		// 1 s
	std::cout << quantity<millisecond>(1*seconds) << std::endl;	// 1000 ms
	std::cout << quantity<microsecond>(1*seconds) << std::endl;	// 1e+006 us
	std::cout << quantity<nanosecond>(1*seconds) << std::endl;	// 1e+009 ns

	std::cout << std::endl;

	std::cout << quantity<second>(1*seconds) << std::endl;		// 1 s
	std::cout << quantity<second>(1*milliseconds) << std::endl;	// 0.001 s
	std::cout << quantity<second>(1*microseconds) << std::endl;	// 1e-006 s
	std::cout << quantity<second>(1*nanoseconds) << std::endl;	// 1e-009 s

	std::cout << std::endl;

	std::cout << quantity<kilometer>(1*meters) << std::endl;	// 0.001 km
	std::cout << quantity<meter>(1*meters) << std::endl;		// 1 m
	std::cout << quantity<centimeter>(1*meters) << std::endl;	// 100 cm
	std::cout << quantity<millimeter>(1*meters) << std::endl;	// 1000 mm

	std::cout << std::endl;

	std::cout << quantity<meter>(1*kilometers) << std::endl;	// 1000 m
	std::cout << quantity<meter>(1*meters) << std::endl;		// 1 m
	std::cout << quantity<meter>(1*centimeters) << std::endl;	// 0.01 m
	std::cout << quantity<meter>(1*millimeters) << std::endl;	// 0.001 m

	return 0;
}

コンセプトとしては、quantityには単数形の、値を作るためには複数形の単位を使用するという方向で。
1 seconds なんて、ネイティブには気持ち悪いんだろうけど、日本人なのでキニシナイ。