编译时排除部分函数模板

Exclude part of function template during compile time

请考虑以下代码。它是一个函数模板,根据其位宽对 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。

我会计算有问题的班次,以便:

  • 当要执行shift时,它有要求的值32,
  • 如果不应该执行,它有一些小值0:

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

您可以使用类似于 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;
}

我终于在没有任何模板的情况下解决了这个问题。我改用普通重载。我将代码分成几部分,每种类型都有一个函数,将这些函数从 64 位宽度级联到 8 位宽度。