编译时位掩码的递归模板
Recursive template for compile-time bit mask
我正试图使用元编程技术创建一个编译时位掩码,我的想法是创建这样的东西:
unsigned int Mask3 = Mask<2>(); // value = 0x03 = b00000000000000000000000000000011
unsigned int Mask3 = Mask<3>(); // value = 0x07 = b00000000000000000000000000000111
unsigned int Mask3 = Mask<7>(); // value = 0x7F = b00000000000000000000000001111111
我正在尝试的代码是:
template <const unsigned int N> const unsigned int Mask()
{
if (N <= 1)
{
return 1;
}
else
{
return ((1 << N) | Mask<N - 1>());
}
}
返回1;
但它导致了成吨的警告:
- 警告C4554:"<lt;':检查运算符优先级是否存在可能的错误
- 警告C4293:"<lt;':偏移计数为负数或过大
最后,编译错误:
- 错误C1202:递归类型或函数依赖关系上下文太复杂
因此,我推断递归性永远不会结束,并落入编译器的无限循环中,但我不明白为什么。
正如已经指出的,您依赖于运行时检查停止编译时递归,这是不起作用的。更重要的是,也许,对于你想要做的事情,你正在定义一个函数,直到你调用它才有价值。所以即使在你停止使用特殊化的递归,仍然有一个嵌套序列函数,这些函数将在运行时调用。
如果想要完整的编译时评估,则必须定义静态数据类模板的成员,因为这是编译时的唯一方式常量可以出现在模板中。类似于:
template <unsigned int N>
struct Mask
{
static unsigned int const value = (1 << (N - 1)) | Mask<N - 1>::value;
};
template <>
struct Mask<0>
{
static unsigned int const value = 0;
};
(我也纠正了你弄错的数值。)
当然,你不需要这么复杂的东西。以下内容应该做到这一点:
template <unsigned int N>
struct Mask
{
static unsigned int const value = (1 << (N + 1)) - 1;
};
template <>
struct Mask<0>
{
static unsigned int const value = 0;
};
(您仍然需要0的专用化。否则,0表示所有位设置。)
当然,最后:要访问值,您需要编写一些内容如CCD_ 1。(您可能需要将其封装在宏中。)
它不需要递归。这应该很好:
template <const unsigned int N> const unsigned int Mask()
{
return ((1 << N) - 1);
}
实际上,它甚至不需要成为一个模板。一个(内联的)函数是可以的。
请注意,如果您希望支持N
的任何值,特别是N >= sizeof(unsigned int) * CHAR_BIT
,您可能希望将其视为特殊情况。
模板是在编译时创建的,但您依赖于运行时行为来停止递归。
例如,如果实例化Mask<2> ,它将使用Mask<1> ,将使用Mask<0>,它将使用Mask<-1> 等
运行时检查N是否为<=1,但这在编译时没有帮助。它仍然创建了一个无限序列的函数。
要削弱模板实例化递归,您需要引入一个显式专门化:
template <0> const unsigned int Mask()
{
return 1;
}
递归永远不会结束,因为编译器试图为两个if分支生成模板实现。因此,当它生成Mask<0>它还生成Mask<0xffffffff>等等
C++11——没有递归或模板:
constexpr unsigned mask(unsigned N) { return unsigned(~(-1<<N)); }
到目前为止,答案只解决了第二个错误(C1202),但您提出的问题不止于此。
警告C4554是由涉及模板参数和<lt;操作人员因此,(1<<N)生成警告。如果N是一个普通的参数,当然不会有任何警告。
非常简单的解决方法是使用(1<<(N))而不是(1<<N),C4554就消失了!
- 通过递归进行因子分解
- 递归函数计算序列中的平方和(并输出过程)
- 使用递归的数组的最小值.这是怎么回事
- 递归列出所有目录中的C++与Python与Ruby的性能
- 递归计数给定目录的文件和所有目录
- 如何在BST的这个简单递归实现中消除警告
- C++:正在检查LinkedList中的回文-递归方法-错误
- 递归模板化函数不能分配给具有常量限定类型"const tt &"的变量"state"
- 递归无序映射
- TSP递归解的迭代形式
- 如何在Elixir中调用递归函数并行
- 返回递归调用和仅递归调用的区别
- 数组元素打印的递归方法
- 使用递归时获取变量的奇怪值
- 如何在C++中递归地按相反顺序打印集合
- 到连接组件算法的问题(递归)
- 如何使用递归打印修改后的星号三角形图案
- 递归函数,用于使用位掩码 c++ 显示集合的所有子集
- 编译时位掩码的递归模板
- 获得所有向量元素组合的递归vs位掩码