2012-02-13 6 views
7

GCC 4.7のようにすぐにユーザ定義リテラル(UDL)が用意されましたので、(物理的な)ユニットライブラリ(例えばBoost.Units)を使用しています1+3i,3m,3meterまたは13_meterのようなリテラルの表現を容易にする。誰でもこの動作をサポートするUDLを使用してBoost.Unitsへの拡張を書いていますか?物理ブースト.Unitsユーザ定義リテラル

+1

UDLをサポートする唯一のコンパイラがGCCであり、不安定なリリースであったとしても、私はこれを推測していません。また、 '_ 'で始まらないUDLは将来の標準用に予約されています。あなた自身で書くことはできません。 –

+0

これは知っておいてよかった!私は、UDLが現在の数字のリテラルサフィックス「l」、「f」、および「d」とどのように競合するか疑問に思っていました。 '_'要件はその質問に答えます。 –

答えて

5

誰もこのような拡張子を持っていません。 gcc(そしておそらくIBM?)だけがUDLを持っているので、しばらく時間がかかるかもしれません。私はいくつかの種類のユニットがtr2になることを期待しています。それが起こるなら、ユニットのためのUDLが出てくると確信しています。

これは動作します:

// ./bin/bin/g++ -std=c++0x -o units4 units4.cpp 

#include <boost/units/unit.hpp> 
#include <boost/units/quantity.hpp> 
#include <boost/units/systems/si.hpp> 

using namespace boost::units; 
using namespace boost::units::si; 

quantity<length, long double> 
operator"" _m(long double x) 
{ return x * meters; } 

quantity<si::time, long double> 
operator"" _s(long double x) 
{ return x * seconds; } 

int 
main() 
{ 
    auto l = 66.6_m; 
    auto v = 2.5_m/6.6_s; 
    std::cout << "l = " << l << std::endl; 
    std::cout << "v = " << v << std::endl; 
} 

私はあなたの好きなユニットを通過し、これを行うにはあまりにも難しいことではないと思います。

ライブラリにこれらを入れることについて: リテラル演算子は名前空間のスコープ関数です。接尾辞の競争は醜くなるでしょう。私は(私がいた場合、ブースト)次に、ユーザーは、あなたが一般的に使用する他のすべての使用declsとともに

using boost::units::literals; 

を行うことができますブースト

namespace literals 
{ 
... 
} 

を持っているでしょう。それでは、例えば std::tr2::unitsで争うことはありません。同様にあなた自身をロールするならば。

+1

Annoyance#1:リテラル演算子は、いくつかの引数型しか取ることができません。 floatとdoubleとlong doubleを返すバージョンを使用するといいでしょう。計算は常にlong doubleに昇格されません。 ADLは戻り値の型だけでは選択できません - 精度固有の名前空間と?ああ。 – emsr

+1

不愉快な#2:すべてのユニットに加えて、少なくとも共通の倍数を持つのが良いでしょう。例えば周波数の「Hz」、「kHz」、「MHz」、「GHz」の長さは「m」ではなく「km」、「cm」、「mm​​」となります。それは退屈になるかもしれない - またはいくつかのマクロを含む。 – emsr

+0

私は_higher precision_へのプロモーションがなぜあなたにとって問題であるのだろうと思っています... – celticminstrel

3

私の意見では、Boost.Unitsのリテラルの使用ではあまり効果がありません。なぜなら、より強力な構文が既存の機能でも達成できるからです。

単純なケースでは、リテラルのように見えますが、間もなくそれはあまり強力ではないことがわかります。 たとえば、1m/s(1メートル/秒)をどのように表現するのかなど、組み合わせた単位のリテラルを定義する必要がありますか?

現在:

auto v = 1*si::meter/si::second; // yes, it is long 

が、リテラルと?

// fake code 
using namespace boost::units::literals; 
auto v = 1._m_over_s; // or 1._m/si::second; or 1._m/1_s // even worst 

より良い解決策は、既存の機能を実現することができます。そして、これは私が何をすべきかです:

namespace boost{namespace units{namespace si{ //excuse me! 
namespace abbreviations{ 
    static const length    m = si::meter; 
    static const time    s = si::second; 

    // ... 
} 
}}} // thank you! 

using namespace si::abbreviations; 
auto v = 1.*m/s; 

あなたが行うことができます同様に:auto a = 1.*m/pow<2>(s);以上の略語を拡張します(例えばstatic const area m2 = pow<2>(si::meter);を)したい場合

あなたがこれ以上他に何をしたいですか?

多分合わせ溶液を

auto v = 1._m/s; // _m is literal, /s is from si::abbreviation combined with operator/ 

方法かもしれないが、そこにあまり冗長コードであるとゲインは最小である(数後_によって*を置換します。)

私の解決策の1つの欠点は、一般的な1文字の名前で名前空間をポーリングすることです。しかし、私は1.*m_/s_のようにアンダースコア(省略形の最初または最後に)を追加する以外は方法を見ませんが、少なくとも私は実際の単位式を構築できます。

関連する問題