Line data Source code
1 : //* This file is part of the MOOSE framework 2 : //* https://mooseframework.inl.gov 3 : //* 4 : //* All rights reserved, see COPYRIGHT for full restrictions 5 : //* https://github.com/idaholab/moose/blob/master/COPYRIGHT 6 : //* 7 : //* Licensed under LGPL 2.1, please see LICENSE for details 8 : //* https://www.gnu.org/licenses/lgpl-2.1.html 9 : 10 : #pragma once 11 : 12 : #include <functional> 13 : #include <map> 14 : 15 : #include "libmesh/parameters.h" 16 : 17 : #include "MooseError.h" 18 : 19 : #ifdef MOOSE_UNIT_TEST 20 : #include "gtest/gtest.h" 21 : class GTEST_TEST_CLASS_NAME_(ParameterRegistryTest, add); 22 : class GTEST_TEST_CLASS_NAME_(ParameterRegistryTest, addExists); 23 : class GTEST_TEST_CLASS_NAME_(ParameterRegistryTest, set); 24 : class GTEST_TEST_CLASS_NAME_(ParameterRegistryTest, setNotRegistered); 25 : class GTEST_TEST_CLASS_NAME_(ParameterRegistryTest, setCatchMooseError); 26 : #endif 27 : 28 : namespace hit 29 : { 30 : class Field; 31 : } 32 : 33 : namespace Moose 34 : { 35 : 36 : /** 37 : * Registry that allows for the typeless setting of a parameter value 38 : * from a hit field 39 : */ 40 : class ParameterRegistry 41 : { 42 : public: 43 : /** 44 : * Get the singleton registry 45 : */ 46 : static ParameterRegistry & get(); 47 : 48 : /** 49 : * Add a parameter 50 : */ 51 : template <class T, class F> 52 : char add(F && f); 53 : 54 : /** 55 : * Sets a parameter value given a hit field 56 : */ 57 : void set(libMesh::Parameters::Value & value, const hit::Field & field) const; 58 : 59 : private: 60 : /** 61 : * Constructor; private so that it can only be created with the singleton 62 : */ 63 56786 : ParameterRegistry() {}; 64 : 65 : #ifdef MOOSE_UNIT_TEST 66 : FRIEND_TEST(::ParameterRegistryTest, add); 67 : FRIEND_TEST(::ParameterRegistryTest, addExists); 68 : FRIEND_TEST(::ParameterRegistryTest, set); 69 : FRIEND_TEST(::ParameterRegistryTest, setNotRegistered); 70 : FRIEND_TEST(::ParameterRegistryTest, setCatchMooseError); 71 : #endif 72 : 73 : /// Registration map of type -> function to fill each type 74 : std::map<std::string, std::function<void(libMesh::Parameters::Value & value, const hit::Field &)>> 75 : _registry; 76 : }; 77 : 78 : template <class T, class F> 79 : char 80 13506311 : ParameterRegistry::add(F && f) 81 : { 82 : static_assert(std::is_invocable_r_v<void, F &, T &, const hit::Field &>, 83 : "Setter function must be callable with (T &, const hit::Field &) and return void"); 84 : 85 : // We register a function that stores T &, but the registry will only ever be 86 : // called from a bare libMesh::Parameters::Value. Thus, we need to cast the 87 : // bare Value to the derived value and then call the setter. 88 19050083 : auto setter = [f = std::forward<F>(f)](libMesh::Parameters::Value & param_value, 89 : const hit::Field & field) -> void 90 : { 91 2771959 : auto cast_param_value = dynamic_cast<libMesh::Parameters::Parameter<T> *>(¶m_value); 92 : mooseAssert(cast_param_value, "Cast failed"); 93 2771959 : f(cast_param_value->set(), field); 94 : }; 95 : 96 13506311 : const auto key = demangle(typeid(T).name()); 97 13506311 : const auto it_inserted_pair = _registry.emplace(key, std::move(setter)); 98 : 99 13506311 : if (!it_inserted_pair.second) 100 1 : mooseError("ParameterRegistry: Parameter with type '", key, "' is already registered"); 101 : 102 13506310 : return 0; 103 13506311 : } 104 : 105 : } // end of namespace Moose