问题
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.
This is what I'm trying (and failing) to make work.
#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>();
}
Error C1202 (recursive type or function dependency context too complex) occurs when compiling.
Error output:
... 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
...
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>();
}
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
?
回答1:
The ternary conditional in this case is not equivalent to if
statement because it is a constexpr if
statement.
With constexpr if
statement,
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.
Note that if you replace the constexpr if
with normal if
you get the same error.
See DEMO.
来源:https://stackoverflow.com/questions/54478729/error-c1202-stack-overflow-when-recursively-computing-a-templated-value-or-fun