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 <span>
28#include <stdexcept>
29#include <string>
30#include <type_traits>
31#include <unordered_map>
32#include <utility>
33#include <vector>
34
35namespace ScriptInterface {
36
37/**
38 * @brief Bind parameters in the script interface.
39 *
40 * This class implements @c ScriptInterfaceBase, binding
41 * the parameters added by add_parameters or by the constructor.
42 * To use it, derive from this class and add parameters. For example,
43 * given a class A
44 * ~~~{.cpp}
45 * class A {
46 * public:
47 * int i() { return m_i; }
48 * private:
49 * int m_i;
50 * };
51 * ~~~
52 * that should have @c i exposed, this can be achieved by extending it
53 * like this:
54 * ~~~{.cpp}
55 * class A : public AutoParameters {
56 * public:
57 * A() : AutoParameters({"name_for_i", i}) {}
58 * int i() { return m_i; }
59 * private:
60 * int m_i;
61 * };
62 * ~~~
63 *
64 * If there is more complicated logic needed, specific setters and
65 * getters can be provided. E.g. given a class B like
66 * ~~~{.cpp}
67 * class B {
68 * public:
69 * void set_i(int);
70 * int get_i();
71 * private:
72 * int m_i;
73 * };
74 * ~~~
75 * we can use a lambdas to set and get the parameter like this:
76 * ~~~{.cpp}
77 * class B : public AutoParameters {
78 * public:
79 * B() : AutoParameters({"name_for_i",
80 * [this](Variant const& v) {set_i(get_value<int>(v));},
81 * [this]() {return get_i();}
82 * }) {}
83 * void set_i(int);
84 * int get_i();
85 * private:
86 * int m_i;
87 * };
88 * ~~~
89 * (this has to be captured in the lambdas to have access to the member
90 * functions of the class).
91 */
92template <typename Derived, typename Base = ObjectHandle>
93class AutoParameters : public Base {
94 static_assert(std::is_base_of_v<ObjectHandle, Base>);
95
96public:
97 /** @brief Exception thrown when accessing an unknown parameter */
98 struct UnknownParameter : public Exception {
99 explicit UnknownParameter(std::string const &name)
100 : Exception("Unknown parameter '" + name + "'.") {}
101 };
102
103 /** @brief Exception thrown when writing to a read-only parameter */
104 struct WriteError : public Exception {
105 explicit WriteError(std::string const &name)
106 : Exception("Parameter '" + name + "' is read-only.") {}
107 };
108
109protected:
110 AutoParameters() = default;
111 explicit AutoParameters(std::vector<AutoParameter> &&params) {
112 add_parameters(std::move(params));
113 }
114
115 void add_parameters(std::vector<AutoParameter> &&params) {
116 for (auto const &p : params) {
117 if (m_parameters.count(p.name)) {
118 m_parameters.erase(p.name);
119 if (auto const it = std::ranges::find(m_key_order, p.name);
120 it != m_key_order.end()) {
121 m_key_order.erase(it);
122 }
123 }
124 m_key_order.emplace_back(p.name);
125 m_parameters.emplace(p.name, std::move(p));
126 }
127 }
128
129 auto const &get_parameter_insertion_order() const { return m_key_order; }
130
131public:
132 /* ObjectHandle implementation */
133 std::span<const boost::string_ref> valid_parameters() const final {
134 static std::vector<boost::string_ref> valid_params;
135 valid_params.clear();
136
137 for (auto const &p : m_parameters) {
138 valid_params.emplace_back(p.first);
139 }
140
141 return valid_params;
142 }
143
144 Variant get_parameter(const std::string &name) const final {
145 try {
146 return m_parameters.at(name).get();
147 } catch (std::out_of_range const &) {
148 throw UnknownParameter{name};
149 }
150 }
151
152 void do_set_parameter(const std::string &name, const Variant &value) final {
153 try {
154 m_parameters.at(name).set(value);
155 } catch (AutoParameter::WriteError const &) {
156 throw WriteError{name};
157 } catch (std::out_of_range const &) {
158 throw UnknownParameter{name};
159 }
160 }
161
162 std::vector<std::pair<std::string, Variant>>
163 serialize_parameters() const final {
164 std::vector<std::pair<std::string, Variant>> parameter_pack{};
165 auto const params = this->get_parameters();
166 for (auto const &key : m_key_order) {
167 parameter_pack.emplace_back(key, params.at(key));
168 }
169 return parameter_pack;
170 }
171
172private:
173 /** @brief Data structure for the stored parameters. */
174 std::unordered_map<std::string, AutoParameter> m_parameters;
175 /** @brief Keep track of the insertion order of parameters. */
176 std::vector<std::string> m_key_order;
177};
178} // namespace ScriptInterface
Bind parameters in the script interface.
AutoParameters(std::vector< AutoParameter > &&params)
void do_set_parameter(const std::string &name, const Variant &value) final
std::span< const boost::string_ref > 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.
boost::string_ref name() const
boost::make_recursive_variant< None, bool, int, std::size_t, double, std::string, ObjectRef, Utils::Vector3b, Utils::Vector3i, Utils::Vector2d, Utils::Vector3d, Utils::Vector4d, std::vector< int >, std::vector< double >, std::vector< boost::recursive_variant_ >, std::unordered_map< int, boost::recursive_variant_ >, std::unordered_map< std::string, boost::recursive_variant_ > >::type Variant
Possible types for parameters.
Definition Variant.hpp:67
static SteepestDescentParameters params
Currently active steepest descent instance.
Exception thrown when accessing an unknown parameter.
Exception thrown when writing to a read-only parameter.