在编译期间排除功能模板的一部分

时间:2016-11-12 09:27:34

标签: c++ c++11 templates bit-shift compile-time

请考虑以下代码。它是一个函数模板,根据其位宽取决于<!--Create frame and assign callbacks to event handlers--> <button type="button" onclick="increaseRadius()">Increase Radius</button> <button type="button" onclick="decreaseRadius()">Decrease Radius</button> <canvas id="myCanvas" width="400" height="400" style="border:1px solid #000000;"></canvas>类型。实际代码更复杂,但这无关紧要:

T

我也使用8位类型。在那种情况下,我会收到警告(参见注释行)。遗憾的是,即使使用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 } } } } ,C ++也无法在编译期间评估if条件。我可以抑制警告,但这对我来说似乎很骇人听闻。我宁愿在编译时排除有问题的代码。

如何解决这个问题(可能不会破坏代码并且不会造成冗余)?

我正在使用GCC 5.4.0。

3 个答案:

答案 0 :(得分:1)

我计算出有问题的转变,以便:

  • 当要执行换档时,它具有所需的值32,
  • 如果不应该执行它,它有一些小值0:

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

答案 1 :(得分: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;
}

答案 2 :(得分:0)

我终于解决了这个没有任何模板。我用简单的重载代替了。我将代码分解成各个类型的单个函数,将这些函数从64位宽度级联到8位宽度。