运行时生成可变参数列表及正方形多维MeshGrid模板适配需求
Alright, let's tackle this problem head-on. You've got a flexible MeshGrid template that handles non-square grids (like MeshGrid<float, 4,5,6>), and you want to adapt it for square grids (all dimensions have the same resolution N_RES across N_DIMS dimensions) plus add support for runtime-generated variadic parameter lists. Here's how to make it work:
1. Adapt the Template for Square Grids
First, we'll create a wrapper template that maps your square grid parameters (N_DIMS, N_RES) to the original variadic MeshGrid template. We'll use C++ template metaprogramming to repeat N_RES exactly N_DIMS times as the variadic arguments.
#include <utility> #include <cmath> // Keep your existing generic MeshGrid template intact template<typename T, size_t... DIMS> class MeshGrid { // Your original implementation here... public: // Example helper to calculate total elements (C++17 fold expression) static constexpr size_t total_elements() { return (DIMS * ...); } }; // Wrapper template for square grids: N_DIMS dimensions, each with N_RES elements template<typename T, size_t N_DIMS, size_t N_RES> class SquareMeshGrid; // Helper specialization to expand the variadic arguments using index sequences template<typename T, size_t N_DIMS, size_t N_RES, size_t... Idx> class SquareMeshGrid<T, N_DIMS, N_RES, std::index_sequence<Idx...>> : public MeshGrid<T, (static_cast<void>(Idx), N_RES)...> { public: static constexpr size_t N_ELEMS = static_cast<size_t>(std::pow(N_RES, N_DIMS)); }; // Public interface that auto-generates the index sequence template<typename T, size_t N_DIMS, size_t N_RES> class SquareMeshGrid : public SquareMeshGrid<T, N_DIMS, N_RES, std::make_index_sequence<N_DIMS>> {};
How this works:
SquareMeshGrid<float, 3, 4>will automatically expand toMeshGrid<float, 4,4,4>under the hood, perfectly matching your square grid requirement.- The
N_ELEMSconstant calculates the total number of elements exactly as you specified:std::pow(N_RES, N_DIMS).
2. Runtime Variadic Parameter Generation
Since C++ template parameters are compile-time constants, we can't directly create a MeshGrid with runtime-determined N_DIMS or N_RES. Instead, we have two practical approaches depending on your needs:
Option A: Variant for Finite Dimension Limits (C++17+)
If your use case only needs to support a fixed set of dimension counts (e.g., up to 8 dimensions), use std::variant to hold different MeshGrid types:
#include <variant> #include <stdexcept> // Factory function to create square grids at runtime template<typename T> auto make_square_meshgrid(size_t n_dims, size_t n_res) { switch(n_dims) { case 1: return MeshGrid<T, n_res>{}; case 2: return MeshGrid<T, n_res, n_res>{}; case 3: return MeshGrid<T, n_res, n_res, n_res>{}; case 4: return MeshGrid<T, n_res, n_res, n_res, n_res>{}; // Add more cases for the maximum dimensions you need to support default: throw std::invalid_argument("Unsupported dimension count"); } }
Option B: Type Erasure for Flexible Interfaces
If you need a unified interface for any supported dimension count, use type erasure to wrap MeshGrid instances behind a common base class:
#include <memory> #include <stdexcept> // Base class for type erasure class MeshGridBase { public: virtual size_t total_elements() const = 0; virtual ~MeshGridBase() = default; }; // Wrapper to adapt MeshGrid to the base class template<typename T, size_t... DIMS> class MeshGridWrapper : public MeshGridBase { MeshGrid<T, DIMS...> impl; public: size_t total_elements() const override { return MeshGrid<T, DIMS...>::total_elements(); } // Add other virtual methods here to expose your MeshGrid's functionality }; // Factory function to create type-erased square grids at runtime template<typename T> std::unique_ptr<MeshGridBase> make_square_meshgrid(size_t n_dims, size_t n_res) { switch(n_dims) { case 1: return std::make_unique<MeshGridWrapper<T, n_res>>(); case 2: return std::make_unique<MeshGridWrapper<T, n_res, n_res>>(); case 3: return std::make_unique<MeshGridWrapper<T, n_res, n_res, n_res>>(); // Extend as needed default: throw std::invalid_argument("Dimension count exceeds supported limit"); } }
Usage Examples
Compile-Time Square Grid
// 3-dimensional square grid, 4 elements per dimension SquareMeshGrid<float, 3, 4> square_grid; // Equivalent to MeshGrid<float, 4,4,4>
Runtime-Generated Grid
// Create a 3D grid with 4 elements per dimension at runtime auto runtime_grid = make_square_meshgrid<float>(3, 4); std::cout << "Total elements: " << runtime_grid->total_elements() << "\n"; // Outputs 64
内容的提问来源于stack exchange,提问作者Patrizio Bertoni

