BDSIM
BDSIM is a Geant4 extension toolkit for simulation of particle transport in accelerator beamlines.
Loading...
Searching...
No Matches
published.h
1/*
2Beam Delivery Simulation (BDSIM) Copyright (C) BDSIM Collaboration, 2001 - 2026.
3
4This file is part of BDSIM.
5
6BDSIM is free software: you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published
8by the Free Software Foundation version 3 of the License.
9
10BDSIM is distributed in the hope that it will be useful, but
11WITHOUT ANY WARRANTY; without even the implied warranty of
12MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13GNU General Public License for more details.
14
15You should have received a copy of the GNU General Public License
16along with BDSIM. If not, see <http://www.gnu.org/licenses/>.
17*/
18#ifndef PUBLISHED_H
19#define PUBLISHED_H
20
21#include <cmath>
22#include <list>
23#include <set>
24#include <string>
25#include <unordered_map>
26#include <vector>
27
28#include "array.h" // our array header
29
30namespace GMAD
31{
46template<typename C>
48{
49public:
50 bool NameExists(const std::string& name) const {return allNames.count(name) > 0;}
51 std::set<std::string> AllNames() {return allNames;}
53 template <typename T>
54 T get(const C* instance, const std::string& name) const;
55
56protected:
58 template<typename T>
59 void publish(const std::string& name, T C::*mp);
63 void set(C* instance, const std::string& name, double value);
64 void set(C* instance, const std::string& name, GMAD::Array* const& value);
65 template<typename T>
66 void set(C* instance, const std::string& name, const T& value);
68
70 void set(C* instance, const C* instance2, const std::string& name);
71
73 template <typename T>
74 using AttributeMap = typename std::unordered_map<std::string, T C::*>;
75
77 template <typename T>
79
80private:
82 template<typename T>
83 T C::* member(const std::string& name) const;
84
86 std::set<std::string> allNames;
87};
88
89// implementation for templated class needs to be in header
90
91template<typename C>
92template<typename T>
93void Published<C>::publish(const std::string& name, T C::*mp)
94{
95 attribute_map<T>()[name] = mp;
96 allNames.insert(name);
97}
98
99template<typename C>
100void Published<C>::set(C* instance, const std::string& name, double value)
101{
102 // check maps for double, int, bool
103 // tried to do this more general (e.g. with a single map),
104 // but difficult since member pointers have different types
105 // better would be to keep a list of arithmetic types published and loop over those
106 try
107 {
108 double C::* mp = member<double>(name);
109 (instance)->*mp = value;
110 }
111 catch (const std::runtime_error&)
112 {
113 try
114 {
115 int C::* mp = member<int>(name);
116 (instance)->*mp = std::round(value);
117 }
118 catch (const std::runtime_error&)
119 {
120 try
121 {
122 bool C::* mp = member<bool>(name);
123 (instance)->*mp = value;
124 }
125 catch (const std::runtime_error&)
126 {
127 try
128 {
129 long C::* mp = member<long>(name);
130 (instance)->*mp = value;
131 }
132 catch (const std::runtime_error&)
133 {
134 // if not found throw error
135 throw std::runtime_error("Unknown member " + name);
136 }
137 }
138 }
139 }
140}
141
142template<typename C>
143template<typename T>
144void Published<C>::set(C* instance, const std::string& name, const T& value)
145{
146 try
147 {
148 T C::* mp = member<T>(name);
149 (instance)->*mp = value;
150 }
151 catch (const std::runtime_error&)
152 {throw std::runtime_error("Unknown member " + name);}
153}
154
155template<typename C>
156void Published<C>::set(C* instance, const std::string& name, GMAD::Array* const& value)
157{
158 try
159 {
160 std::list<double> valueNew = value->GetDataList();
161 std::list<double> C::* mp = member<std::list<double>>(name);
162 (instance)->*mp = valueNew;
163 }
164 catch (const std::runtime_error&)
165 {
166 try
167 {
168 std::list<std::string> valueNew = value->GetSymbolsList();
169 std::list<std::string> C::* mp = member<std::list<std::string>>(name);
170 (instance)->*mp = valueNew;
171 }
172 catch (const std::runtime_error &)
173 {
174 // if not found throw error
175 throw std::runtime_error("Unknown member " + name);
176 }
177 }
178}
179
180template<typename C>
181void Published<C>::set(C* instance, const C* instance2, const std::string& name)
182{
183 // unfortunately, have to try all existing types
184 try
185 {
186 // pointer to member
187 double C::* mp = member<double>(name);
188 // set value
189 (instance)->*mp = (instance2)->*mp;
190 }
191 catch (const std::runtime_error&)
192 {
193 try
194 {
195 int C::* mp = member<int>(name);
196 (instance)->*mp = (instance2)->*mp;
197 }
198 catch (const std::runtime_error&)
199 {
200 try
201 {
202 bool C::* mp = member<bool>(name);
203 (instance)->*mp = (instance2)->*mp;
204 }
205 catch (const std::runtime_error&)
206 {
207 try
208 {
209 std::string C::* mp = member<std::string>(name);
210 (instance)->*mp = (instance2)->*mp;
211 }
212 catch (const std::runtime_error&)
213 {
214 try
215 {
216 std::list<std::string> C::* mp = member<std::list<std::string>>(name);
217 (instance)->*mp = (instance2)->*mp;
218 }
219 catch (const std::runtime_error&)
220 {
221 try
222 {
223 std::list<int> C::* mp = member<std::list<int>>(name);
224 (instance)->*mp = (instance2)->*mp;
225 }
226 catch (const std::runtime_error&)
227 {
228 try
229 {
230 std::list<double> C::* mp = member<std::list<double>>(name);
231 (instance)->*mp = (instance2)->*mp;
232 }
233 catch (const std::runtime_error&)
234 {
235 try
236 {
237 long C::* mp = member<long>(name);
238 (instance)->*mp = (instance2)->*mp;
239 }
240 catch (const std::runtime_error&)
241 {
242 // if not found throw error
243 throw std::runtime_error("Unknown member " + name);
244 }
245 }
246 }
247 }
248 }
249 }
250 }
251 }
252}
253
254template <typename C>
255template <typename T>
256T Published<C>::get(const C* instance, const std::string& name) const
257{
258 // pointer to member
259 T C::* mp = member<T>(name);
260 return (instance)->*mp;
261}
262
263template<typename C>
264template<typename T>
265T C::* Published<C>::member(const std::string& name) const
266{
267 AttributeMap<T>& m = attribute_map<T>();
268 typename AttributeMap<T>::const_iterator it=m.find(name);
269 if (it == m.end())
270 {
271 // if not found throw error
272 throw std::runtime_error("Unknown member " + name);
273 }
274 else
275 {
276 return it->second;
277 }
278 }
279
280 template<typename C>
281 template<typename T>
282 typename Published<C>::template AttributeMap<T>& Published<C>::attribute_map() const
283 {
284 // static initialisation for flexibility
285 static AttributeMap<T> m;
286 return m;
287 }
288}
289
290#endif
Representation of arrays used in tokens.
Definition array.h:39
Class that provides introspection to its members.
Definition published.h:48
void set(C *instance, const std::string &name, GMAD::Array *const &value)
Definition published.h:156
typename std::unordered_map< std::string, T C::* > AttributeMap
Define AttributeMap of string and class member pointer.
Definition published.h:74
void set(C *instance, const C *instance2, const std::string &name)
Set member with name of class instance to value of second instance.
Definition published.h:181
AttributeMap< T > & attribute_map() const
Access method to static map for type T and class C.
void publish(const std::string &name, T C::*mp)
Make pointer to member from class C and type T with accessible with a name.
Definition published.h:93
void set(C *instance, const std::string &name, const T &value)
Definition published.h:144
std::set< std::string > allNames
A cache of all names defined through publish().
Definition published.h:86
T C::* member(const std::string &name) const
Access to member pointer.
Definition published.h:265
void set(C *instance, const std::string &name, double value)
Definition published.h:100
T get(const C *instance, const std::string &name) const
Get method for class C.
Definition published.h:256
Parser namespace for GMAD language. Combination of Geant4 and MAD.