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