algo — C++23 日本語リファレンス GitHub

検証済み · 最終更新 2026-07-24 · GitHub

固定次元グリッドの範囲判定と一次元化

lib/graph/grid.hpp

インクルード

#include "graph/grid.hpp"

クラス

名前 説明
Grid 固定次元グリッドの範囲判定と一次元化

検証

検証プログラム(1)
実装
#pragma once
#include <cstdint>
#include <utility>

namespace internal {

template <int Index>
struct grid_impl {
    template <class Head, class... Tail>
    constexpr grid_impl(Head &&head, Tail &&...tail) : limit(head), impl(std::forward<Tail>(tail)...) {}

    template <class Head, class... Tail>
    constexpr bool in_field(Head x, Tail &&...tail) const {
        return 0 <= x && x < limit && impl.in_field(std::forward<Tail>(tail)...);
    }

    template <class Head, class... Tail>
    constexpr std::int64_t flatten(Head x, Tail &&...tail) const {
        return x + limit * impl.flatten(std::forward<Tail>(tail)...);
    }

  private:
    std::int64_t limit;
    grid_impl<Index - 1> impl;
};

template <>
struct grid_impl<0> {
    constexpr grid_impl() {}

    constexpr bool in_field() const { return true; }

    constexpr std::int64_t flatten() const { return 0; }
};

}  // namespace internal

/// @brief 固定次元グリッドの範囲判定と一次元化
/// @tparam Index 次元数
/// @complexity 構築・`in_field`・`flatten` は $O(Index)$
template <int Index>
struct Grid {
    /// @brief 各次元の大きさからグリッドを構築する
    /// @complexity $O(Index)$
    template <class... Args>
    constexpr Grid(Args &&...args) : entity(std::forward<Args>(args)...) {
        static_assert(sizeof...(Args) == Index);
    }

    /// @brief 座標が全次元の範囲内か返す
    /// @complexity $O(Index)$
    template <class... Args>
    constexpr bool in_field(Args &&...args) const {
        static_assert(sizeof...(Args) == Index);
        return entity.in_field(std::forward<Args>(args)...);
    }

    /// @brief 座標を行優先の一次元indexへ変換する
    /// @complexity $O(Index)$
    template <class... Args>
    constexpr std::int64_t flatten(Args &&...args) const {
        static_assert(sizeof...(Args) == Index);
        return entity.flatten(std::forward<Args>(args)...);
    }

  private:
    internal::grid_impl<Index> entity;
};

bundled

#line 2 "lib/graph/grid.hpp"
#include <cstdint>
#include <utility>

namespace internal {

template <int Index>
struct grid_impl {
    template <class Head, class... Tail>
    constexpr grid_impl(Head &&head, Tail &&...tail) : limit(head), impl(std::forward<Tail>(tail)...) {}

    template <class Head, class... Tail>
    constexpr bool in_field(Head x, Tail &&...tail) const {
        return 0 <= x && x < limit && impl.in_field(std::forward<Tail>(tail)...);
    }

    template <class Head, class... Tail>
    constexpr std::int64_t flatten(Head x, Tail &&...tail) const {
        return x + limit * impl.flatten(std::forward<Tail>(tail)...);
    }

  private:
    std::int64_t limit;
    grid_impl<Index - 1> impl;
};

template <>
struct grid_impl<0> {
    constexpr grid_impl() {}

    constexpr bool in_field() const { return true; }

    constexpr std::int64_t flatten() const { return 0; }
};

}  // namespace internal

/// @brief 固定次元グリッドの範囲判定と一次元化
/// @tparam Index 次元数
/// @complexity 構築・`in_field`・`flatten` は $O(Index)$
template <int Index>
struct Grid {
    /// @brief 各次元の大きさからグリッドを構築する
    /// @complexity $O(Index)$
    template <class... Args>
    constexpr Grid(Args &&...args) : entity(std::forward<Args>(args)...) {
        static_assert(sizeof...(Args) == Index);
    }

    /// @brief 座標が全次元の範囲内か返す
    /// @complexity $O(Index)$
    template <class... Args>
    constexpr bool in_field(Args &&...args) const {
        static_assert(sizeof...(Args) == Index);
        return entity.in_field(std::forward<Args>(args)...);
    }

    /// @brief 座標を行優先の一次元indexへ変換する
    /// @complexity $O(Index)$
    template <class... Args>
    constexpr std::int64_t flatten(Args &&...args) const {
        static_assert(sizeof...(Args) == Index);
        return entity.flatten(std::forward<Args>(args)...);
    }

  private:
    internal::grid_impl<Index> entity;
};