ESPResSo
Extensible Simulation Package for Research on Soft Matter Systems
Loading...
Searching...
No Matches
AutoParameters.hpp
Go to the documentation of this file.
1/*
2 * Copyright (C) 2010-2022 The ESPResSo project
3 *
4 * This file is part of ESPResSo.
5 *
6 * ESPResSo is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * ESPResSo is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20#pragma once
21
25
26#include <algorithm>
27#include <ranges>
28#include <stdexcept>
29#include <string>
30#include <string_view>
31#include <type_traits>
32#include <unordered_map>
33#include <utility>
34#include <vector>
35
36namespace ScriptInterface {
37
38/**
39 * @brief Bind parameters in the script interface.
40 *
41 * This class implements @c ScriptInterfaceBase, binding
42 * the parameters added by add_parameters or by the constructor.
43 * To use it, derive from this class and add parameters. For example,
44 * given a class A
45 * ~~~{.cpp}
46 * class A {
47 * public:
48 * int i() { return m_i; }
49 * private:
50 * int m_i;
51 * };
52 * ~~~
53 * that should have @c i exposed, this can be achieved by extending it
54 * like this:
55 * ~~~{.cpp}
56 * class A : public AutoParameters {
57 * public:
58 * A() : AutoParameters({"name_for_i", i}) {}
59 * int i() { return m_i; }
60 * private:
61 * int m_i;
62 * };
63 * ~~~
64 *
65 * If there is more complicated logic needed, specific setters and
66 * getters can be provided. E.g. given a class B like
67 * ~~~{.cpp}
68 * class B {
69 * public:
70 * void set_i(int);
71 * int get_i();
72 * private:
73 * int m_i;
74 * };
75 * ~~~
76 * we can use a lambdas to set and get the parameter like this:
77 * ~~~{.cpp}
78 * class B : public AutoParameters {
79 * public:
80 * B() : AutoParameters({"name_for_i",
81 * [this](Variant const& v) {set_i(get_value<int>(v));},
82 * [this]() {return get_i();}
83 * }) {}
84 * void set_i(int);
85 * int get_i();
86 * private:
87 * int m_i;
88 * };
89 * ~~~
90 * (this has to be captured in the lambdas to have access to the member
91 * functions of the class).
92 */
93template <typename Derived, typename Base = ObjectHandle>
94class AutoParameters : public Base {
95 static_assert(std::is_base_of_v<ObjectHandle, Base>);
96
97public:
98 /** @brief Exception thrown when accessing an unknown parameter */
99 struct UnknownParameter : public Exception {
100 explicit UnknownParameter(std::string const &name)
101 : Exception("Unknown parameter '" + name + "'.") {}
102 };
103
104 /** @brief Exception thrown when writing to a read-only parameter */
105 struct WriteError : public Exception {
106 explicit WriteError(std::string const &name)
107 : Exception("Parameter '" + name + "' is read-only.") {}
108 };
109
110protected:
111 // NOLINTNEXTLINE(bugprone-crtp-constructor-accessibility)
112 AutoParameters() = default;
113 // NOLINTNEXTLINE(bugprone-crtp-constructor-accessibility)
114 explicit AutoParameters(std::vector<AutoParameter> &&params) {
115 add_parameters(std::move(params));
116 }
117 ~AutoParameters() override = default;
118
119 bool has_parameter(std::string const &name) const override {
120 return m_parameters.contains(name);
121 }
122
123 void add_parameters(std::vector<AutoParameter> &&params) {
124 for (auto const &p : params) {
125 if (m_parameters.contains(p.name)) {
126 m_parameters.erase(p.name);
127 if (auto const it = std::ranges::find(m_key_order, p.name);
128 it != m_key_order.end()) {
129 m_key_order.erase(it);
130 }
131 }
132 m_key_order.emplace_back(p.name);
133 m_parameters.emplace(p.name, std::move(p));
134 }
135 }
136
137 auto const &get_parameter_insertion_order() const { return m_key_order; }
138
139public:
140 /* ObjectHandle implementation */
141 std::vector<std::string_view> valid_parameters() const final {
142 auto const view = std::views::elements<0>(m_parameters);
143 return {view.begin(), view.end()};
144 }
145
146 Variant get_parameter(const std::string &name) const final {
147 try {
148 return m_parameters.at(name).get();
149 } catch (std::out_of_range const &) {
150 throw UnknownParameter{name};
151 }
152 }
153
154 void do_set_parameter(const std::string &name, const Variant &value) final {
155 try {
156 m_parameters.at(name).set(value);
157 } catch (AutoParameter::WriteError const &) {
158 throw WriteError{name};
159 } catch (std::out_of_range const &) {
160 throw UnknownParameter{name};
161 }
162 }
163
164 std::vector<std::pair<std::string, Variant>>
166 std::vector<std::pair<std::string, Variant>> parameter_pack{};
167 auto const params = this->get_parameters();
168 for (auto const &key : m_key_order) {
169 parameter_pack.emplace_back(key, params.at(key));
170 }
171 return parameter_pack;
172 }
173
174private:
175 /** @brief Data structure for the stored parameters. */
176 std::unordered_map<std::string, AutoParameter> m_parameters;
177 /** @brief Keep track of the insertion order of parameters. */
178 std::vector<std::string> m_key_order;
179};
180} // namespace ScriptInterface
Bind parameters in the script interface.
AutoParameters(std::vector< AutoParameter > &&params)
bool has_parameter(std::string const &name) const override
void do_set_parameter(const std::string &name, const Variant &value) final
~AutoParameters() override=default
std::vector< std::string_view > valid_parameters() const final
Variant get_parameter(const std::string &name) const final
std::vector< std::pair< std::string, Variant > > serialize_parameters() const final
void add_parameters(std::vector< AutoParameter > &&params)
auto const & get_parameter_insertion_order() const
VariantMap get_parameters() const
Get current parameters.
std::string_view name() const
T get_value(Variant const &v)
Extract value of specific type T from a Variant.
static SteepestDescentParameters params
Currently active steepest descent instance.
Exception thrown when accessing an unknown parameter.
Exception thrown when writing to a read-only parameter.
Recursive variant implementation.
Definition Variant.hpp:84