私は、 GoingNative 2012 (23:00 から)で Stroustrup によって提示されたユーザー定義リテラルを使用して、ユニットの実装をいじってみました。コードは次のとおりです。
#include <iostream>
using std::cout;
using std::endl;
template<int M, int K, int S>
struct Unit { // a unit in the MKS system
enum {m=M,kg=K,s=S};
};
template<typename Unit> // a magnitude with a unit
struct Value {
double val;
constexpr Value(double d) : val(d) {}
};
using Meter = Unit<1,0,0>;
using Second = Unit<0,0,1>;
using Distance = Value< Meter >;
using Time = Value< Second >;
using Velocity = Value< Unit<1,0,-1> >;
constexpr Value<Meter> operator "" _m(long double d)
// a f-p literal with suffix 'm'
{
return Distance(d);
}
constexpr Value<Second> operator"" _s(long double d)
// a f-p literal with suffix 's'
{
return Time(d);
}
constexpr Velocity operator/(Distance d, Time t)
{
return ( d.val / t.val );
}
int main(void)
{
Distance s = 100._m;
Time t = 22._s;
Velocity v = s/t;
cout << "s " << s.val << "\nt " << t.val << endl;
cout << "v " << v.val << endl;
return 0;
}
ご覧のとおり、自由に を定義しoperator/
て速度を計算しました。出力は次のとおりです (gcc-4.7 が必要です)。
$ g++ -std=c++0x test_units_02.cc && ./a.out
s 100
t 22
v 4.54545
ここまでは順調ですね。ここで、単位表現を含む文字列を構造体 Unit (または Value?) に追加したいと考えています。どんな方法でも書けるようになりたい
cout << "v " << v.val << v.unit << endl;
そして、次のようなものを取得します
v 4.54545 m^1 s^-1
また
v 4.54545 m^1 kg^0 s^-1
確認用なので綺麗である必要はありません。そして、それを行う方法を学びます;)。
もちろん、洗練された解決策は、コンパイル時にすべてを評価することです。
私はそれにいくつかのショットを持っていましたが、結果のない試みであなたを退屈させたり混乱させたりすることはありません...