https://mooseframework.inl.gov
ParameterRegistry.h
Go to the documentation of this file.
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 #include <typeinfo>
15 #include <typeindex>
16 
17 #include "libmesh/parameters.h"
18 
19 #include "MooseError.h"
20 #include "MooseUtils.h"
21 
22 #ifdef MOOSE_UNIT_TEST
23 #include "gtest/gtest.h"
24 class GTEST_TEST_CLASS_NAME_(ParameterRegistryTest, add);
25 class GTEST_TEST_CLASS_NAME_(ParameterRegistryTest, addExists);
26 class GTEST_TEST_CLASS_NAME_(ParameterRegistryTest, set);
27 class GTEST_TEST_CLASS_NAME_(ParameterRegistryTest, setNotRegistered);
28 class GTEST_TEST_CLASS_NAME_(ParameterRegistryTest, setCatchMooseError);
29 #endif
30 
31 namespace hit
32 {
33 class Field;
34 }
35 
36 namespace Moose
37 {
38 
44 {
45 public:
49  static ParameterRegistry & get();
50 
54  template <class T, class F>
55  char add(F && f);
56 
60  void set(libMesh::Parameters::Value & value, const hit::Field & field) const;
61 
62 private:
67 
68 #ifdef MOOSE_UNIT_TEST
69  FRIEND_TEST(::ParameterRegistryTest, add);
70  FRIEND_TEST(::ParameterRegistryTest, addExists);
71  FRIEND_TEST(::ParameterRegistryTest, set);
72  FRIEND_TEST(::ParameterRegistryTest, setNotRegistered);
73  FRIEND_TEST(::ParameterRegistryTest, setCatchMooseError);
74 #endif
75 
77  std::unordered_map<std::type_index,
78  std::function<void(libMesh::Parameters::Value & value, const hit::Field &)>>
80 };
81 
82 template <class T, class F>
83 char
85 {
86  static_assert(std::is_invocable_r_v<void, F &, T &, const hit::Field &>,
87  "Setter function must be callable with (T &, const hit::Field &) and return void");
88 
89  // We register a function that stores T &, but the registry will only ever be
90  // called from a bare libMesh::Parameters::Value. Thus, we need to cast the
91  // bare Value to the derived value and then call the setter.
92  auto setter = [f = std::forward<F>(f)](libMesh::Parameters::Value & param_value,
93  const hit::Field & field) -> void
94  {
95  auto cast_param_value = dynamic_cast<libMesh::Parameters::Parameter<T> *>(&param_value);
96  mooseAssert(cast_param_value, "Cast failed");
97  f(cast_param_value->set(), field);
98  };
99 
100  const std::type_index key(typeid(T));
101  const auto it_inserted_pair = _registry.emplace(key, std::move(setter));
102 
103  if (!it_inserted_pair.second)
104  mooseError("ParameterRegistry: Parameter with type '",
105  MooseUtils::prettyCppType<T>(),
106  "' is already registered");
107 
108  return 0;
109 }
110 
111 } // end of namespace Moose
std::unordered_map< std::type_index, std::function< void(libMesh::Parameters::Value &value, const hit::Field &)> > _registry
Registration map of type -> function to fill each type.
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application...
Definition: MooseError.h:323
Registry that allows for the typeless setting of a parameter value from a hit field.
ParameterRegistry()
Constructor; private so that it can only be created with the singleton.
class GTEST_TEST_CLASS_NAME_(ParameterRegistryTest, add)
Real value(unsigned n, unsigned alpha, unsigned beta, Real x)
Definition: Moose.h:42
FRIEND_TEST(::ParameterRegistryTest, add)
char add(F &&f)
Add a parameter.
MOOSE now contains C++17 code, so give a reasonable error message stating what the user can do to add...