2015-02-07 40 views
0

說我有一個簡單的函數,它是這樣的:如何在模板中定義浮點常量。避免在運行時強制轉換

template<typename T> 
T get_half(T a){ 
    return 0.5*a; 
} 

這個功能通常將T爲雙或浮點數進行評估。 該標準規定0.5將是一個雙精度浮點數(0.5f)。 如何編寫上面的代碼,以使0.5總是T型的,這樣在評估產品或返回時就不會有投射? 我想要的是0.5在編譯時是T的常量。這個問題的關鍵是我想在運行時避免轉換。

例如,如果我寫的:

template<typename T> 
T get_half(T a){ 
    return T(0.5)*a; 
} 

我可以絕對肯定的是T(0.5)在編譯時評價?如果不是,那麼完成此操作的正確方法是什麼?如果需要,我可以使用C++ 11。

預先感謝您。

在C++ 11我有一個numeric_traits類的東西如下(頭文件內)

template<typename Scalar> 
struct numeric_traits{ 
    static constexpr Scalar one_half = 0.5; 
    //Many other useful constants .... 
}; 

所以我的代碼中我會爲使用:

template<typename T> 
T get_half(T a){ 
    return numeric_traits<T>::one_half*a; 
} 

這做什麼我希望ie 0.5在編譯時以我需要的精度解決,並且在運行時不會發生強制轉換。然而,缺點是:

  • 我需要每次我需要一個新的常數
  • 的sintax時間修改numeric_traits可能過於冗長煩人? (當然不是一個大問題)
  • 這將是很好也許有這樣的:常量(0.5),它在運行時解析爲T型。

再次提前謝謝。

+0

IIRC應用於文字的顯式轉換被認爲是'constexpr',所以是的,它在編譯時被評估。 – 2015-02-07 17:17:33

+1

@ TheParamagneticCroissant在運行時仍然可以評估常量表達式中有效的東西。在編譯時需要評估表達式的場景比你想像的要少。 – hvd 2015-02-07 17:24:07

+0

@TheParamagneticCroissant比你的評論。有關我的編輯的反饋會很高興。 – Alejandro 2015-02-10 14:39:43

回答

2

沒有也不可能有任何方法迫使常量在運行時永遠不能計算,因爲有些機器根本沒有單個指令來加載所有可能的類型值。例如,機器可能只有一個16位加載常量指令,其中0x12345678需要在運行時計算爲0x1234 << 16 | 0x5678。或者,這樣一個常量可能會從內存中加載,但這可能比計算成本更高。

你需要相信你的編譯器。在可行的系統上,任何具有任何優化量的編譯器都會按照與0.5f相同的方式翻譯T(0.5),假設Tfloat。並且0.5f將以您的平臺最明智的方式進行計算。這可能涉及將其加載爲常量,或者可能涉及計算它。或者誰知道,你的編譯器可能會將T(0.5)*a更改爲a/2,如果它給出相同的結果。

在你的問題中,你給出了一個添加numeric_traits輔助類的例子。這是IMO的做法。在這種constexpr有差別極不可能的情況下,你可以只寫

template <typename T> 
T get_half(T a) { 
    constexpr T half = 0.5; 
    return half * a; 
} 

然而,這仍然弊大於利,在我看來:你get_half現在可以不再與非文字類型的使用。它要求該類型支持在常量表達式中從double轉換。假設你有一個任意精度的rational類型,但沒有考慮constexpr。現在您的get_half不能使用,因爲初始化constexpr T half = 0.5;無效,即使0.5 * a可能已編譯。

即使您的numeric_traits輔助類也是如此;它不是僅僅因爲我將它移入函數體而失效。

+0

謝謝你的回答。我知道編譯器可能會優化類似T(0.5)的東西。我想我的問題是最好的做法是,如果我想101%確定雙常數將是雙重的,並且浮動常數將是浮動的。例如,我可以在C++ 11的數字特徵類中使用constexpr。還有其他解決方案嗎? – Alejandro 2015-02-10 14:26:11

+0

@Ale:您已經在您的問題中展示瞭解決方案:) – 2015-02-10 14:41:32

+0

@LightnessRacesinOrbit謝謝。我想我想知道有更多經驗和最佳實踐的人的意見。此外,解決方案將使用c + + 98(沒有c + + 11功能)? – Alejandro 2015-02-10 15:44:58

相關問題