2016-11-12 75 views
1

請考慮下面的代碼。它是一個功能模板,根據其位寬,根據類型T進行操作。實際的代碼更復雜,但這是無關緊要的:在編譯時排除函數模板的一部分

template <typename T> T MyFunc(T t) 
{ 
    constexpr const uint8_t typeBitCount = sizeof(T)*8; 

    // more code here that works fine for all widths 

    if (typeBitCount >= 32) 
    { 
     if (...) 
     { 
     return t >> 16; // warning right shift count >= width of type 
     } 

     if (typeBitCount >= 64) 
     { 
     if (...) 
     { 
      return t >> 32; // warning right shift count >= width of type 
     } 
     } 
    } 
} 

我也使用這與8位類型。在這種情況下,我會收到警告(請參閱註釋行)。不幸的是,即使使用constexpr,C++也無法在編譯期間評估if條件。我大概可以壓制這些警告,但這對我來說似乎很難受。我寧願在編譯時排除有問題的代碼。

如何解決這個問題(可能不會破壞代碼並且不會造成冗餘)?

我正在使用GCC 5.4.0。

+0

所有的代碼都需要編譯。取決於'typeBitCount'的選擇只發生在運行時,而不是編譯時。因此,當編譯器進入這些行時,您會收到警告。 –

+0

這完全清楚。問題是如何解決這個儘可能乾淨。 – Silicomancer

+0

如果你有一個C++ 14編譯器,你可能可以使整個函數成爲一個'constexpr'函數,並讓它評估一個編譯時間(取決於「更多代碼在這裏......」部分)。這可能會解決你的一些問題。或者你可以專門爲8位類型的函數,並將通用的「更多代碼在這裏......」部分放在一個單獨的函數中。 –

回答

0

我終於解決了這個沒有任何模板。我使用純重載代替。我將代碼分解爲每個類型的單個函數,將這些函數從64位寬度級聯到8位寬度級別。

1

我計算問題的移位,以便:

  • 時要執行的移位,它具有所需的值32,
  • 如果它不應該被執行時,它也有一些小值0:

    .... 
    constexpr uint8_t shift2 = (typeBitCount >= 64) ? 32 : 0; 
    .... 
    if (typeBitCount >= 64) 
        { 
        if (...) 
        { 
         return t >> shift2; 
        } 
        } 
    .... 
    
1

您可以使用類似於this answer模板偏特化來實現依賴於類型的功能使用函數的大小:

// Base implementation for unsupported size and type. 
template <typename T, size_t TSize> 
class MyFuncImpl; 

// 32-bit specialization. 
template <typename T> 
struct MyFuncImpl<T, 4> 
{ 
    T operator()(const T t) const 
    { 
     return t >> 16; 
    } 
}; 

// 64-bit specialization. 
template <typename T> 
struct MyFuncImpl<T, 8> 
{ 
    T operator()(const T t) const 
    { 
     return t >> 32; 
    } 
}; 

// Calling this functor will calculate the correct bit-shift at compile time and not emit warnings. 
template <typename T> 
T MyFunc(const T t) 
{ 
    return MyFuncImpl<T, sizeof(T)>()(t); 
} 

您還可以爲8位和16位類型添加額外的特化項。你會這樣使用它:

int main() 
{ 
    uint32_t test1 = 1235434; 
    std::cout << MyFunc(test1) << std::endl; 

    return 0; 
}