2016-10-01 33 views
4

我正在尋找一種慣用的方法來優化我寫的這個模板。根據其他參數計算模板參數的習慣方式

我主要關心的是如何正確定義模板參數n並將其用作返回參數,而用戶不得覆蓋它。

我也打開其他建議,關於如何以慣用的C++ 14方式編寫此模板。

template< 
    typename InType=uint32_t, 
    typename OutType=float, 
    unsigned long bits=8, 
    unsigned long n=(sizeof(InType) * 8)/bits 
> 
std::array<OutType,n> hash_to_color(InType in) noexcept {  
    InType mask = ~0; 
    mask = mask << bits; 
    mask = ~mask; 
    std::array<OutType,n> out; 
    auto out_max = static_cast<OutType>((1 << bits) - 1); 
    for (auto i = 0; i < n; i++) { 
    auto selected = (in >> (i * bits)) & mask; 
    out[i] = static_cast<OutType>(selected)/out_max; 
    } 
    return out; 
} 
+0

,也許你可以'static_assert'它的正確值:

您可以使用此像往常一樣? –

回答

3

關於n模板參數,你可以通過使用auto避免它作爲返回值類型在C++ 14。這是一個更簡單的原理示例:

template<int N> 
auto f() 
{ 
    constexpr int bar = N * 3; 
    std::array<int, bar> foo; 
    return foo; 
} 

當然,數組模板參數的計算必須是一個常量表達式。

另一種選擇(用C++ 11兼容)是後返回型:

template<int N> 
auto f() -> std::array<int, N * 3> 
{ 

這比利用的C++ 14的允許返回類型推演從更詳細的一丁點兒return聲明。

注:~0在你的代碼是錯誤的,因爲0int,它應該是~(InType)0。另外(1 << bits) - 1有潛在的溢出問題。

+0

謝謝。這很有幫助。我在問題代碼中刪除了一些'static_assert',它確保這些位不會被'static_assert(bits somnium

2

我認爲M.M.的答案非常好,在你的情況下,我肯定會使用其中一個建議。

假設你以後遇到,給出Ñ的情況下,所述邏輯,使用不3 N,但更復雜的東西,例如,Ñ2 + 3的n + 1。或者,也許邏輯不是很複雜,但它可能會改變。

(只是爲了再次澄清,我不認爲這是你的問題或MM的回答的情況下顯著的問題。)

所以,第三個選擇將分解出邏輯到constexpr功能:

#include <array> 

constexpr int arr_size(int n) { return n * n + 3 * n + 1; } 

由於它是constexpr,它可以被用於實例化的模板:

template<int N> 
std::array<int, arr_size(N)> f() { 
    return std::array<int, arr_size(N)>(); 
} 

請注意,現在該函數具有明確的返回類型,但邏輯arr_size只出現一次。如果你想確保用戶不會覆蓋它

int main() { 
    auto a = f<10>(); 
    a[0] = 3; 
}