条件演算子を使用しているときにテンプレート化された値または関数を再帰的に計算するときのエラーC1202(スタックオーバーフロー)

z1ne2wo

ゲームボードのセルの座標をこのセルの数に変換する機会を提供する機能を実装しています。

これは私が仕事をしようとしている(そして失敗している)ものです。

#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(再帰型または関数従属コンテキストが複雑すぎる)が発生します。

エラー出力:

... 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は常に真ですが、そうではないはずです。

私はこの機能を次のように実装しようとしました:

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 statementを使用するconditional operator (a ? b : c)と、同じエラーが発生します。

使用すると実際にここで何が起こりますconditional operatorか?

PW

この場合の3項条件は、ステートメントであるため、ステートメント同等ではありませんifconstexpr if

constexpr if声明、

もしconstexpr if文はテンプレートの実体内に表示され、条件がインスタンス化後の値に依存しない場合に囲むテンプレートをインスタンス化するときに、廃棄された文は、インスタンス化されていません。

ただし、3値条件を使用すると、テンプレートは常にインスタンス化されます。これにより、無限再帰が発生します。

constexpr ifを通常に置き換えるif、同じエラーが発生することに注意してください。DEMOを参照してください

この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。

侵害の場合は、連絡してください[email protected]

編集
0

コメントを追加

0

関連記事

Related 関連記事

ホットタグ

アーカイブ