以下片段返回 T 类型(假定为无符号)整数的下一个最高幂。它通过重复移位位来实现。
出于所有意图和目的,我在位移循环中使用的无符号类型足够大,可以表示(名义上)65536 位数。实际上,因此可以保持“原样”。
template <class T>
T supremum_2(T k) {
if (k == T(0)) return T(1);
k--;
for (int i=1; i<sizeof(T)*8; i++) k |= k >> i;
return k+1;
}
做一个专业的工作,应该在编译时选择循环计数器的类型,以保证它能够跨越 sizeof(T)*8 而不会溢出。
这可以在编译时使用 std::numeric_traits 完成吗?如果有怎么办?
从概念上讲,我希望能够编写如下内容:
typedef unsigned_type_that_can_represent<sizeof(T)*8> counter_type;
...
...
for (counter_type i(1); i<sizeof(T)*8; i<<=1) k = k | k >> i;
...
基于以下讨论,我决定添加以下上下文。
换一种方式:
我们如何保证在编译时为模板代码的内部工作选择有效的(只要它们需要的大)和合适的类型?如果我们发现自己在模板代码中使用具体类型,我们可能会通过潜在的不透明路径对模板的类型做出无意的假设。
例如,如果我们坚持使用(比如说)一个 int 作为计数器,那么一切都会正常工作,直到有人将模板代码与他们的 bigint 库一起使用。这可以表示具有比 int 表示的更多二进制数字的整数。因此,我们是否应该将类型 unsigned long long 设为 long?当然,这只会延迟问题(尽管很长一段时间)?这个解决方案有“640K - 对每个人都足够大”或静态数组大小的阴影。
在这种情况下,显而易见但有些低效的选择是将计数器的类型设置为与数字 k 的类型相同。它(原则上)是低效的,因为我们只要求计数器能够表示与 k 的位数相对应的数字。对于其他情况,这可能是错误的假设。
一般情况呢?看起来元编程是一种合适的方法。如何保持这种“理智”?也许,正式地,要求是编译时函数将(可能派生的)抽象类型要求映射到类型。
也许这是 YABL(Yet Another Boost Library)的工作!
【抱歉乱说】