diff --git a/res/cmake/test.cmake b/res/cmake/test.cmake index 1f7331b1d..4c975ba71 100644 --- a/res/cmake/test.cmake +++ b/res/cmake/test.cmake @@ -21,6 +21,7 @@ if (test AND ${PHARE_EXEC_LEVEL_MIN} GREATER 0) # 0 = no tests add_subdirectory(tests/core/utilities/range) add_subdirectory(tests/core/utilities/index) add_subdirectory(tests/core/utilities/indexer) + add_subdirectory(tests/core/utilities/meta) add_subdirectory(tests/core/utilities/cellmap) #add_subdirectory(tests/core/numerics/boundary_condition) add_subdirectory(tests/core/numerics/interpolator) diff --git a/src/core/utilities/meta/meta_utilities.hpp b/src/core/utilities/meta/meta_utilities.hpp index 3bea76ba3..0d753b452 100644 --- a/src/core/utilities/meta/meta_utilities.hpp +++ b/src/core/utilities/meta/meta_utilities.hpp @@ -2,6 +2,7 @@ #define PHARE_CORE_UTILITIES_META_META_UTILITIES_HPP #include +#include #include #include "core/utilities/types.hpp" @@ -17,7 +18,7 @@ namespace core struct dummy { using type = int; - static const type value = 0; + static type const value = 0; }; @@ -69,6 +70,7 @@ namespace core using SimulatorOption = std::tuple...>; + constexpr decltype(auto) possibleSimulators() { // inner tuple = dim, interp, list[possible nbrParticles for dim/interp] @@ -81,6 +83,43 @@ namespace core SimulatorOption, InterpConst<3>, 4, 5, 8, 9, 25>>{}; } + constexpr static auto n_possibleSimulators() + { + return std::tuple_size_v; + } + + template + auto static constexpr validNbrParticlesFor( + std::tuple const&) + { + return std::tuple{}; + } + + template + auto static constexpr simulatorTupleIndex() + { + std::int64_t idx = -1; + auto constexpr simulators_list = possibleSimulators(); + auto constexpr predicate = [](auto i, auto& idx) constexpr -> void { + using SimuType = std::decay_t(simulators_list))>; + constexpr std::tuple_element_t<0, SimuType> _dim{}; + constexpr std::tuple_element_t<1, SimuType> _interp{}; + if constexpr (dim == _dim() and interp == _interp()) + idx = i; + }; + + for_N(predicate, idx); + + assert(idx >= 0); + return static_cast(idx); + } + + template + auto static constexpr validNbrParticlesFor() + { + return validNbrParticlesFor( + std::get()>(possibleSimulators())); + } template // used from PHARE::amr::Hierarchy auto makeAtRuntime(std::size_t dim, Maker&& maker) @@ -90,7 +129,7 @@ namespace core core::apply(possibleSimulators(), [&](auto const& simType) { using SimuType = std::decay_t; - using _dim = typename std::tuple_element<0, SimuType>::type; + using _dim = std::tuple_element_t<0, SimuType>; if (!p) p = maker(dim, _dim{}); diff --git a/src/core/utilities/types.hpp b/src/core/utilities/types.hpp index ee90667ad..a262eb73f 100644 --- a/src/core/utilities/types.hpp +++ b/src/core/utilities/types.hpp @@ -226,7 +226,7 @@ namespace core NO_DISCARD inline std::optional get_env(std::string const& key) { - if (const char* val = std::getenv(key.c_str())) + if (char const* val = std::getenv(key.c_str())) return std::string{val}; return std::nullopt; } @@ -424,8 +424,8 @@ enum class for_N_R_mode { forward_tuple, }; -template -constexpr auto for_N(Fn& fn) +template +constexpr auto for_N(Fn& fn, Args&&... args) { /* // how to use for_N<2>([](auto ic) { @@ -435,8 +435,8 @@ constexpr auto for_N(Fn& fn) */ static_assert(std::is_same_v); - using return_type - = std::decay_t>>; + using return_type = std::decay_t< + std::invoke_result_t, Args&...>>; constexpr bool returns = !std::is_same_v; if constexpr (returns) @@ -444,24 +444,24 @@ constexpr auto for_N(Fn& fn) return std::apply( [&](auto... ics) { if constexpr (M == for_N_R_mode::make_tuple) - return std::make_tuple(fn(ics)...); + return std::make_tuple(fn(ics, args...)...); else if constexpr (M == for_N_R_mode::make_array) - return std::array{fn(ics)...}; + return std::array{fn(ics, args...)...}; else if constexpr (M == for_N_R_mode::forward_tuple) - return std::forward_as_tuple(fn(ics)...); + return std::forward_as_tuple(fn(ics, args...)...); else throw std::runtime_error("unknown return mode"); }, apply_N(Apply{})); } else - std::apply([&](auto... ics) { (fn(ics), ...); }, apply_N(Apply{})); + std::apply([&](auto... ics) { (fn(ics, args...), ...); }, apply_N(Apply{})); } -template -constexpr auto for_N(Fn&& fn) +template +constexpr auto for_N(Fn&& fn, Args&&... args) { - return for_N(fn); + return for_N(fn, args...); } template diff --git a/tests/core/utilities/meta/CMakeLists.txt b/tests/core/utilities/meta/CMakeLists.txt new file mode 100644 index 000000000..f04907970 --- /dev/null +++ b/tests/core/utilities/meta/CMakeLists.txt @@ -0,0 +1,20 @@ + +cmake_minimum_required (VERSION 3.20.1) + +project(test-meta-utilities) + +set(SOURCES test_meta_utilities.cpp) + +add_executable(${PROJECT_NAME} ${SOURCES}) + +target_include_directories(${PROJECT_NAME} PRIVATE + ${GTEST_INCLUDE_DIRS} + ) + +target_link_libraries(${PROJECT_NAME} PRIVATE + phare_core + ${GTEST_LIBS}) + +add_no_mpi_phare_test(${PROJECT_NAME} ${CMAKE_CURRENT_BINARY_DIR}) + + diff --git a/tests/core/utilities/meta/test_meta_utilities.cpp b/tests/core/utilities/meta/test_meta_utilities.cpp new file mode 100644 index 000000000..b43edabbc --- /dev/null +++ b/tests/core/utilities/meta/test_meta_utilities.cpp @@ -0,0 +1,30 @@ +#include +#include +#include + +#include "core/utilities/meta/meta_utilities.hpp" + +#include "gtest/gtest.h" + +using namespace PHARE::core; + +struct MetaUtilitiesTest : public ::testing::Test +{ +}; + +TEST(MetaUtilitiesTest, testvalidNbrParticlesFor) +{ + std::size_t constexpr static dim = 2; + std::size_t constexpr static interp = 2; + + auto constexpr validNbrParticlesTuple = validNbrParticlesFor(); + auto constexpr n_validNbrParticles = std::tuple_size_v; + EXPECT_EQ(n_validNbrParticles, 5); +} + +int main(int argc, char** argv) +{ + ::testing::InitGoogleTest(&argc, argv); + + return RUN_ALL_TESTS(); +}