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 <stdexcept>
27#include <string>
28#include <type_traits>
29#include <unordered_map>
30#include <utility>
31#include <vector>
32
33namespace ScriptInterface {
34
35/**
36 * @brief Bind parameters in the script interface.
37 *
38 * This class implements @c ScriptInterfaceBase, binding
39 * the parameters added by add_parameters or by the constructor.
40 * To use it, derive from this class and add parameters. For example,
41 * given a class A
42 * ~~~{.cpp}
43 * class A {
44 * public:
45 * int i() { return m_i; }
46 * private:
47 * int m_i;
48 * };
49 * ~~~
50 * that should have @c i exposed, this can be achieved by extending it
51 * like this:
52 * ~~~{.cpp}
53 * class A : public AutoParameters {
54 * public:
55 * A() : AutoParameters({"name_for_i", i}) {}
56 * int i() { return m_i; }
57 * private:
58 * int m_i;
59 * };
60 * ~~~
61 *
62 * If there is more complicated logic needed, specific setters and
63 * getters can be provided. E.g. given a class B like
64 * ~~~{.cpp}
65 * class B {
66 * public:
67 * void set_i(int);
68 * int get_i();
69 * private:
70 * int m_i;
71 * };
72 * ~~~
73 * we can use a lambdas to set and get the parameter like this:
74 * ~~~{.cpp}
75 * class B : public AutoParameters {
76 * public:
77 * B() : AutoParameters({"name_for_i",
78 * [this](Variant const& v) {set_i(get_value<int>(v));},
79 * [this]() {return get_i();}
80 * }) {}
81 * void set_i(int);
82 * int get_i();
83 * private:
84 * int m_i;
85 * };
86 * ~~~
87 * (this has to be captured in the lambdas to have access to the member
88 * functions of the class).
89 */
90template <typename Derived, typename Base = ObjectHandle>
91class AutoParameters : public Base {
92 static_assert(std::is_base_of_v<ObjectHandle, Base>);
93
94public:
95 /** @brief Exception thrown when accessing an unknown parameter */
96 struct UnknownParameter : public Exception {
97 explicit UnknownParameter(std::string const &name)
98 : Exception("Unknown parameter '" + name + "'.") {}
99 };
100
101 /** @brief Exception thrown when writing to a read-only parameter */
102 struct WriteError : public Exception {
103 explicit WriteError(std::string const &name)
104 : Exception("Parameter '" + name + "' is read-only.") {}
105 };
106
107protected:
108 AutoParameters() = default;
109 explicit AutoParameters(std::vector<AutoParameter> &&params) {
110 add_parameters(std::move(params));
111 }
112
113 void add_parameters(std::vector<AutoParameter> &&params) {
114 for (auto const &p : params) {
115 if (m_parameters.count(p.name)) {
116 m_parameters.erase(p.name);
117 for (auto it = m_key_order.begin(); it != m_key_order.end(); ++it) {
118 if (*it == p.name) {
119 m_key_order.erase(it);
120 break;
121 }
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 */
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)
Utils::Span< const boost::string_ref > valid_parameters() const final
void do_set_parameter(const std::string &name, const Variant &value) 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
A stripped-down version of std::span from C++17.
Definition Span.hpp:38
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:80
static SteepestDescentParameters params
Currently active steepest descent instance.
Exception thrown when accessing an unknown parameter.
Exception thrown when writing to a read-only parameter.