2016-05-25 78 views
7

目前我正在重寫/擴展我的C++實用程序庫,並考慮到新的C++ 11功能。其中一個新增功能是模板類,它可以在編譯時提供一組數字的最大值。是否可以在編譯時檢查const值是否已知?

template<typename T, T... Xs> class ConstMax 
{ 
private: 
    template<typename... Ts> static constexpr T Max(Ts... xs); 

    template<typename Tx> static constexpr T Max(Tx x) 
    { 
     return x; 
    } 

    template<typename T1, typename T2, typename... Ts> static constexpr T Max(T1 x, T2 y, Ts... xs) 
    { 
     return y > x ? Max<T2, Ts...>(y, xs...) : Max<T1, Ts...>(x, xs...); 
    } 

public: 
    static const T Value = Max(Xs...); 
}; 

一個例子使用這個類:

int max = ConstMax<int, 1, 8, 66, 32, 90, 12, 33>::Value; 

這裏另一個例子可能使其難以覈實,如果ConstMax < ...> ::值在編譯時實際評估:

template<typename... Ts> class Variant 
{ 
public: 
    static const size_t MaxValueSize = ConstMax<size_t, sizeof(Ts)...>::Value; 
}; 

其中產品max = 90。我使用gdb加入了這段代碼,看起來在賦值max時沒有執行函數調用。

我的問題:

  1. 我可以有把握地認爲ConstMax<...>::Value總是在編譯的時候知道的?
  2. 有沒有辦法檢查constexpr函數/方法是否在編譯時進行評估?
  3. 我明白定義爲constexpr在編譯時不一定評估成員/方法/函數,它的事實,Value被定義爲這個static const改變任何東西,我是更好實施這一特定情況下,遞歸模板類?

回答

3
  1. 我可以有把握地認爲ConstMax < ...> ::值始終是在編譯時已知?

是的,因爲它是用一個常量表達式初始化的。但我會修改Valueconstexpr而不是const

  1. 有沒有辦法檢查constexpr函數/方法是否在編譯時被評估?

是的。嘗試在constexpr表達式中使用它們。如果有效,它們將在編譯時進行評估。如果編譯失敗,那麼編譯時就不會進行評估。

  • 我明白成員/方法/定義爲constexpr未在編譯時期間必然評估函數,這是否值被定義爲靜態常量改變什麼瞭解這個或是這樣的事實我最好將這個特定的案例作爲遞歸模板類來實現?
  • 如果您在常量表達式中使用成員,則會迫使它們在編譯時進行評估。所以如果你關心,我只需確保以常量表達式來評估它們(通過constexpr)。

    +0

    感謝您的快速響應。我更喜歡使用遞歸模板的constexpr方法,很高興知道這不會影響評估時間。 – Charlie

    +0

    如何在編譯時通過調用它來告訴函數是否是constexpr?如果其中一個參數不是constexpr,那麼調用會失敗,對嗎? – Alex

    +0

    @Alex:是的,如果您嘗試在常量表達式中計算函數,並且它不是常量表達式,則編譯將失敗。 – Cornstalks

    3

    要檢查表達式是否爲constexpr(即常量表達式),你可以使用std::integral_constant型特點如下:

    #include <iostream> 
    #include <type_traits> 
    
    template<typename T, T... Xs> class ConstMax { 
        template<typename... Ts> static constexpr T Max(Ts... xs); 
        template<typename Tx> static constexpr T Max(Tx x) { return x;} 
        template<typename T1, typename T2, typename... Ts> 
        static constexpr T 
        Max(T1 x, T2 y, Ts... xs) { 
         return y > x ? Max<T2, Ts...>(y, xs...) : Max<T1, Ts...>(x, xs...); 
        } 
    public: 
        static const T Value = Max(Xs...); 
    }; 
    
    int main() { 
    std::cout << std::integral_constant<int, ConstMax<int, 1, 8, 66, 32, 90, 12, 33>::Value>::value << std::endl; 
    } 
    

    Live Demo

    如果不是constexpr它會破壞編譯過程。

    +0

    謝謝,這將成爲我單元測試的一個非常好的擴展。 – Charlie