在这种情况下,为什么模板即时深度超过限制?
Why does the template instantion depth exceed the limit in this case?
我在C++中输入此代码:
#include <iostream>
template <int n, int i = 0>
class show {
public:
show () {
if (i % 2) {
std::cout << i << std::endl;
show <n-1, i+1>();
}else {
show <n,i+1>();
}
}
};
template <int i>
class show <0, i> {};
int main()
{
show <6>();
}
我以为它会写 6 个不能被 2 整除的前几个数字。相反,我收到一个错误
致命错误:模板即时超过最大值 100
如果它最多应该实例化 12 个实例,为什么会出现此错误?
尝试使用
show () {
if ( i % 2 )
std::cout << i << std::endl;
show<n-(i%2 ? 1 : 0), i+1>();
}
或者,如果您可以使用 C++17,也可以使用
show () {
if constexpr (i % 2) {
std::cout << i << std::endl;
show <n-1, i+1>();
}else {
show <n,i+1>();
}
}
代码的问题
show () {
if (i % 2) {
std::cout << i << std::endl;
show <n-1, i+1>();
}else {
show <n,i+1>();
}
}
i % 2
是真还是假并不重要:show
S、show<n-1, i+1>
和show<n, i+1>
都实现了。因此,实现了许多不必要的show
,并达到了模板实例化的最大数量。
C++17 引入if constexpr
正是为了避免此类问题。
在 C++17 之前,你可以用
show<n-(i%2 ? 1 : 0), i+1>();
在函数show()
中:
show () {
if (i % 2) {
std::cout << i << std::endl;
show <n-1, i+1>();
}else {
show <n,i+1>();
}
}
类模板show
在子句的两个部分中实例化if
。
您需要切换到if constexpr
才能执行单个正确的实例:
show () {
if constexpr (i % 2) {
std::cout << i << std::endl;
show <n-1, i+1>();
}else {
show <n,i+1>();
}
}
例
为了了解发生了什么,让我们尝试"内联"更简单表达式的实例化show<1>()
:
在第一个递归级别,我们将得到:
if (0 % 2) {
std::cout << 0 << std::endl;
show <0,1>(); // <-- this will instantiate to a no-op.
} else {
show <1,1>();
}
这是第二个:
if (0 % 2) {
std::cout << 0 << std::endl;
} else {
show <1,1>(); // <-- now this will instantiate
}
第三:
if (0 % 2) {
std::cout << 0 << std::endl;
} else {
if (1 % 2) {
std::cout << 1 << std::endl;
show <0,1>(); // <-- this will instantiate to a no-op.
} else {
show <1,2>();
}
}
第四:
if (0 % 2) {
std::cout << 0 << std::endl;
} else {
if (1 % 2) {
std::cout << 1 << std::endl;
} else {
show <1,2>(); // <-- now this will instantiate
}
}
第五:
if (0 % 2) {
std::cout << 0 << std::endl;
} else {
if (1 % 2) {
std::cout << 1 << std::endl;
} else {
if (1 % 2) {
std::cout << 2 << std::endl;
show <0,2>(); // <-- this will again instantiate to a no-op...
} else {
show <1,3>(); // <-- ... and I'm sure you can see where this is going.
}
}
}
这说明了其他答案已经指出的内容:模板是代码生成器。这意味着,如果编译器到达模板,它将始终从该模板生成代码,而不管程序在到达该模板之前具有任何逻辑。
这就是if constexpr
阻止的。如果if constexpr
处的表达式计算结果为 falsy 值,编译器将忽略所述if constexpr
块内的任何代码。
如果您没有 C++17 编译器,则可以使用 SFINAE 获得相同的结果。
相关文章:
- 我是c ++的新手,你能解释一下在这种情况下的指针吗
- 在这种情况下,java对象是否可以调用本机函数
- 在这种情况下显式调用时,std::cout 如何更改析构函数的行为?
- 在这种情况下,我真的复制了字节还是复制了字符?
- 为什么在这种情况下,bool 类型的输出等于 0?
- 在这种情况下,如何传递成员函数而不是函数?
- 为什么在这种情况下递增阵列名称有效?
- 在这种情况下我应该使用哪种设计模式
- 为什么在这种情况下我需要 .template
- 在这种情况下,使用 string_view 是否会导致不必要的字符串复制?
- 我是否访问了已释放的内存,或者在这种情况下DrMemory报告不正确?
- 在这种情况下,"typename..."意味着什么?
- 为什么在这种情况下 x = 44?
- 在这种情况下是私有的吗?试图使操作员<<过载
- 在这种情况下,如何防止C++输出/控制台窗体关闭
- 为什么 lambda nullptr 取消引用在这种情况下有效?
- 为什么在这种情况下,前向声明不起作用?
- 为什么在这种情况下不调用我的虚拟函数实现?
- 在这种情况下,为什么模板即时深度超过限制?
- 在这种情况下,当尝试从单独的类更新变量时,我是否需要使用指针?