2012-11-14 14 views
4

我使用Stroustrup在GoingNative 2012(從分鐘23:00開始)提供的用戶定義字面值來實現單元實現。下面是代碼:如何將從模板參數導出的編譯時信息添加到模板中?

#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 

到目前爲止好。現在我想向結構單元(或值?)添加一個包含單元表示的字符串。我wnat無論怎樣才能夠寫

cout << "v " << v.val << v.unit << endl; 

,並得到類似

v 4.54545 m^1 s^-1 

v 4.54545 m^1 kg^0 s^-1 

它並不需要是美麗的,因爲這將只是檢查。並學習如何去做;)。

當然,優雅的解決方案將在編譯時評估一切。

我有一些球吧,但我不會孔/混淆你與我無結果的嘗試......

+0

@Xeo:示例代碼是使用「user-defined-literals」和「constexpr」特性的C++ 11。爲什麼不這樣標記? – steffen

+3

因爲問題的主題與此無關嗎? :)我可以構建一個不使用這些東西的例子。另外,如果問題的*主題*僅爲C++ 11特性,我個人認爲問題應該僅標記爲「[C++ 11]」。 – Xeo

回答

5

首先我們添加一個unit成員Value

template<typename Unit> // a magnitude with a unit 
struct Value { 
    double val; 
    constexpr static Unit unit = {}; 
    constexpr Value(double d) : val(d) {} 
}; 

然後我們寫流了運營商:

template<int M, int K, int S> 
std::ostream &operator<<(std::ostream &os, Unit<M, K, S>) { 
    return os << "m^" << M << " kg^" << K << " s^" << S; 
} 

生成在編譯時字符串是可能,但需要constexpr編譯時字符串類(例如boost::mpl::string)和十進制格式 - 所有這些都是可行的,但在這種情況下並不特別值得。

+0

看起來不錯。但是我得到一個鏈接器錯誤:未定義的引用'Value > :: unit'' – steffen

+1

@steffen:由於您的ODR使用'unit',因此您需要提供一個定義。 '模板 constexpr單位值 ::單位;'在'Value'定義之後就足夠了。 – Xeo

+0

@Xeo謝謝;只是通過值傳遞流出參數更容易。 – ecatmur

相關問題