编译时排除部分函数模板
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 位宽度。
请考虑以下代码。它是一个函数模板,根据其位宽对 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 位宽度。