2013-03-04 5 views
11

C++11user-defined literalsです。私はちょうどそれらと一緒に遊んで始めました。それは私が定義する1つのリテラルにすべてSI multipliersを自動的に追加することが可能かどうか疑問に思いましたか?例えば単一のユーザー定義リテラルに基づいてリテラル定義を自動的に追加する方法はありますか?

、IはLengthいくつかUnitsベースクラスのサブクラスであり、Iは(boost operatorsと同じ趣旨で)追加SI乗算器を自動的するメカニズムを持っていると思い

Length operator "" _m(long double m) { 
    return Length(m); // Length in meters 
} 

を定義する場合返すすべてのリテラルのLength

// these are added automatically when defining the literal "_m": 
             // Length in: 
Length operator "" _Ym(long double Ym); // Yottameters 
Length operator "" _Zm(long double Zm); // Zetameters 
...          // ... 
...          // ... 
Length operator "" _km(long double km); // kilometers 
Length operator "" _mm(long double mm); // millimeters 
...          // ...  
...          // ... 
Length operator "" _zm(long double zm); // zeptometers 
Length operator "" _ym(long double ym); // yoctometers 

は、私の知る限りは、おそらくいくつかのマクロの魔法とは別に、見ることができるように、このAを実行する方法はありませんすべてのユーザ定義リテラルが明示的なの定義を必要とするためです。

..私は何か見落としていますか?

+0

なぜテンプレートと? –

+0

@Adriano:example? –

+0

と同じです:http://www.codeproject.com/Articles/447922/Application-of-Cplusplus11-User-Defined-Literals-t(測定単位の部分を省略し、乗数のみを保持できる場合は...その点を逃した、あなたは正しいかもしれません_macro magic_) –

答えて

3

"奇妙なマクロ"がなければ、あなたが求めていることを正確に行う方法はないと思います。これは、私の知る限り得ることができるようです:

template<typename T, T (*op)(long double)> 
struct SI 
{ 
    // ... 
    constexpr static T micro = op (.000001); 
    constexpr static T milli = op (.001); 
    constexpr static T kilo = op (1000); 
    constexpr static T mega = op (1000000); 
    // ... 
}; 

struct Length 
{ 
    constexpr Length(long double d) : _d(d) { } 
    constexpr operator long double() { return _d; } 
    long double _d; 
}; 

constexpr Length operator "" _m(long double m) { 
    return Length(m); 
} 

typedef SI<Length, ::operator "" _m> SI_Length; 

int main() 
{ 
    constexpr Length l = 3 * SI_Length::kilo; 
    static_assert(l == 3000, "error"); 
} 

奇妙なマクロが許可されている場合は、次のようなものがジョブを実行する必要があります。

#define DEFINE_SI_MULTIPLIERS(T, unit) \ 
    constexpr T operator "" _u ## unit(long double m) \ 
    { return ::operator "" _ ## unit(0.000001 * m); } \ 
    constexpr T operator "" _m ## unit(long double m) \ 
    { return ::operator "" _ ## unit(0.001 * m); } \ 
    constexpr T operator "" _k ## unit(long double m) \ 
    { return ::operator "" _ ## unit(1000 * m); } \ 
    // ... 

DEFINE_SI_MULTIPLIERS(Length, m) 

int main() 
{ 
    constexpr Length l = 3.0_km; 
    static_assert(l == 3000, "error"); 
} 
+1

hmm ...素敵な試み(+1)ですが、これは名前空間に定義された 'const' SI要素を単純に乗算することと大きく異なるわけではありません(例えば' Length L = 3 * si :: kilo; ')。 IMHOそれは多くの表現力を追加しません... –

+0

@RodyOldenhuis:True。私が言及したように、これは私が得ることができる限りであり、おそらくそれほど遠くないでしょう。私はマクロがあなたが探しているものを達成する唯一の方法だと信じています。 –

+0

私もそう信じています。受け入れられる! –

-1

フロートを自分で解析したい場合は、operator "" _m(const char *)フレーバーを使用できませんか?これにより、浮動小数点値のための共通のSI認識パーサを呼び出して1234k_mを書くことが可能になります。

+2

あなたはこれがうまくいくのですか? gcc 4.7.2を使用すると、これは '1234'' k_m'として解析され、gccは 'operator" "k_m'を探します。[liveworkspace](http://liveworkspace.org/code/1YjxLZ$0)を参照してください。 –

関連する問題