使用条件运算符递归计算模板值或函数时出现错误C1202(堆栈溢出) [英] Error C1202 (stack overflow) when recursively computing a templated value or function when using a conditional operator

查看:112
本文介绍了使用条件运算符递归计算模板值或函数时出现错误C1202(堆栈溢出)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在实现一种功能,该功能提供了将游戏板单元格的坐标转换为该单元格编号的机会。

I am implementing functionality that provides the opportunity to translate the coordinates of the cells of the game board to the number of this cell.

这就是我

#include <cstdint>
#include <utility>

using UInt32 = std::uint32_t;

template<UInt32... s>
using IndexSequence = std::integer_sequence<UInt32, s...>;

static constexpr UInt32 W = 8;
static constexpr UInt32 H = 8;

template<UInt32 x1, UInt32 x, UInt32 x2, UInt32 y1, UInt32 y2, UInt32... s>
static constexpr auto RegonImpl =
    (y1 <= y2) 
        ? (x <= x2)
            ? RegonImpl<x1, x + 1, x2, y1,     y2, s..., W * y1 + x>
            : RegonImpl<x1, x1,    x2, y1 + 1, y2, s...>
        : IndexSequence<s...>{};

template<UInt32 x1, UInt32 x2, UInt32 y1, UInt32 y2>
static constexpr auto Region = RegonImpl<x1, x1, x2, y1, y2>;

int main() {
    constexpr auto idx = Region<0, 0, 5, 5>();
}

编译时发生错误C1202(递归类型或函数依赖上下文太复杂)。

Error C1202 (recursive type or function dependency context too complex) occurs when compiling.

错误输出:

... Indexes<8,8>::Region<0,0,1,7>(void) noexcept' being compiled
... Indexes<8,8>::RegionImpl<0,0,0,1,7>' being compiled
... Indexes<8,8>::RegionImpl<1,0,0,1,7,0>' being compiled
... Indexes<8,8>::RegionImpl<2,0,0,1,7,0,1>' being compiled
... Indexes<8,8>::RegionImpl<3,0,0,1,7,0,1,2>' being compiled
... Indexes<8,8>::RegionImpl<4,0,0,1,7,0,1,2,3>' being compiled
... Indexes<8,8>::RegionImpl<5,0,0,1,7,0,1,2,3,4>' being compiled
... Indexes<8,8>::RegionImpl<6,0,0,1,7,0,1,2,3,4,5>' being compiled
... Indexes<8,8>::RegionImpl<7,0,0,1,7,0,1,2,3,4,5,6>' being compiled
... Indexes<8,8>::RegionImpl<8,0,0,1,7,0,1,2,3,4,5,6,7>' being compiled
... Indexes<8,8>::RegionImpl<9,0,0,1,7,0,1,2,3,4,5,6,7,8>' being compiled
...

您可以看到条件 x< = x2 始终是真实的,但事实并非如此。

As you can see the condition x <= x2 is always true, which should not be.

我尝试如下实现此功能:

I tried to implement this functionality as follows:

template<UInt32... s, UInt32... t>
constexpr auto concat(IndexSequence<s...>, IndexSequence<t...>) noexcept {
    return IndexSequence<s..., t...>{};
}

template<UInt32 x, UInt32 x1, UInt32 y1, UInt32 x2, UInt32 y2>
static constexpr auto RegionImpl() noexcept {
    if constexpr (y1 <= y2) {
        if constexpr (x <= x2) {
            return concat(IndexSequence<W * y1 + x>{}, RegionImpl<x + 1, x1, y1, x2, y2>());
        } else {
            return RegionImpl<x1, x1, y1 + 1, x2, y2>();
        }
    } else {
        return IndexSequence<>{};
    }
}

template<UInt32 x1, UInt32 y1, UInt32 x2, UInt32 y2>
static constexpr auto Region() noexcept {
    return RegionImpl<x1, x1, y1, x2, y2>();
}

它有效。但是,如果不是使用 if语句来使用条件运算符(a?b:c),则相同发生错误。

It works. But, if instead of the if statement to use the conditional operator (a ? b : c), then the same error occurs.

使用条件运算符时在这里实际发生什么?

What actually happens here when using conditional operator?

推荐答案

在这种情况下,三元条件等同于 if 语句,因为它是 constexpr if 语句。

The ternary conditional in this case is not equivalent to if statement because it is a constexpr if statement.

使用 constexpr if 语句,


如果 constexpr if 语句出现在模板实体中,并且条件在实例化之后不依赖于值,因此在实例化封闭模板时也不会实例化废弃的语句。

If a constexpr if statement appears inside a templated entity, and if condition is not value-dependent after instantiation, the discarded statement is not instantiated when the enclosing template is instantiated .

但是对于三元条件,模板总是被实例化。这导致无限递归。

But with the ternary conditional, the templates are always instantiated. This leads to infinite recursion.

请注意,如果将 constexpr if 替换为普通的 if 您得到相同的错误。
请参见演示

Note that if you replace the constexpr if with normal if you get the same error. See DEMO.

这篇关于使用条件运算符递归计算模板值或函数时出现错误C1202(堆栈溢出)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆