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 - 2023.
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 "array.h"
23#include <list>
24#include <set>
25#include <string>
26#include <unordered_map>
27#include <vector>
28
29namespace GMAD
30{
45 template<typename C>
47 {
48 public:
49 bool NameExists(const std::string& name) const {return allNames.count(name) > 0;}
50
51 protected:
53 template<typename T>
54 void publish(const std::string& name, T C::*mp);
58 void set(C* instance, const std::string& name, double value);
59 void set(C* instance, const std::string& name, GMAD::Array* const& value);
60 template<typename T>
61 void set(C* instance, const std::string& name, const T& value);
63
65 void set(C* instance, const C* instance2, const std::string& name);
66
68 template <typename T>
69 using AttributeMap = typename std::unordered_map<std::string, T C::*>;
70
72 template <typename T>
74
76 template <typename T>
77 T get(const C* instance, const std::string& name) const;
78
79 private:
81 template<typename T>
82 T C::* member(const std::string& name) const;
83
85 std::set<std::string> allNames;
86 };
87
88 // implementation for templated class needs to be in header
89
90 template<typename C>
91 template<typename T>
92 void Published<C>::publish(const std::string& name, T C::*mp)
93 {
94 attribute_map<T>()[name] = mp;
95 allNames.insert(name);
96 }
97
98 template<typename C>
99 void Published<C>::set(C* instance, const std::string& name, double value)
100 {
101 // check maps for double, int, bool
102 // tried to do this more general (e.g. with a single map),
103 // but difficult since member pointers have different types
104 // better would be to keep a list of arithmetic types published and loop over those
105 try {
106 double C::* mp = member<double>(name);
107 (instance)->*mp = value;
108 }
109 catch (const std::runtime_error&) {
110 try {
111 int C::* mp = member<int>(name);
112 (instance)->*mp = value;
113 }
114 catch (const std::runtime_error&) {
115 try {
116 bool C::* mp = member<bool>(name);
117 (instance)->*mp = value;
118 }
119 catch (const std::runtime_error&) {
120 try {
121 long C::* mp = member<long>(name);
122 (instance)->*mp = value;
123 }
124 catch (const std::runtime_error&) {
125 // if not found throw error
126 throw std::runtime_error("Unknown member " + name);
127 }
128 }
129 }
130 }
131 }
132
133 template<typename C>
134 template<typename T>
135 void Published<C>::set(C* instance, const std::string& name, const T& value)
136 {
137 try
138 {
139 T C::* mp = member<T>(name);
140 (instance)->*mp = value;
141 }
142 catch (const std::runtime_error&)
143 {throw std::runtime_error("Unknown member " + name);}
144 }
145
146 template<typename C>
147 void Published<C>::set(C* instance, const std::string& name, GMAD::Array* const& value)
148 {
149 try
150 {
151 std::list<double> valueNew = value->GetDataList();
152 std::list<double> C::* mp = member<std::list<double>>(name);
153 (instance)->*mp = valueNew;
154 }
155 catch (const std::runtime_error&)
156 {
157 try
158 {
159 std::list<std::string> valueNew = value->GetSymbolsList();
160 std::list<std::string> C::* mp = member<std::list<std::string>>(name);
161 (instance)->*mp = valueNew;
162 }
163 catch (const std::runtime_error &)
164 {
165 // if not found throw error
166 throw std::runtime_error("Unknown member " + name);
167 }
168 }
169 }
170
171 template<typename C>
172 void Published<C>::set(C* instance, const C* instance2, const std::string& name)
173 {
174 // unfortunately, have to try all existing types
175 try {
176 // pointer to member
177 double C::* mp = member<double>(name);
178 // set value
179 (instance)->*mp = (instance2)->*mp;
180 }
181 catch (const std::runtime_error&) {
182 try {
183 int C::* mp = member<int>(name);
184 (instance)->*mp = (instance2)->*mp;
185 }
186 catch (const std::runtime_error&) {
187 try {
188 bool C::* mp = member<bool>(name);
189 (instance)->*mp = (instance2)->*mp;
190 }
191 catch (const std::runtime_error&) {
192 try {
193 std::string C::* mp = member<std::string>(name);
194 (instance)->*mp = (instance2)->*mp;
195 }
196 catch (const std::runtime_error&) {
197 try {
198 std::list<std::string> C::* mp = member<std::list<std::string>>(name);
199 (instance)->*mp = (instance2)->*mp;
200 }
201 catch (const std::runtime_error&) {
202 try {
203 std::list<int> C::* mp = member<std::list<int>>(name);
204 (instance)->*mp = (instance2)->*mp;
205 }
206 catch (const std::runtime_error&) {
207 try {
208 std::list<double> C::* mp = member<std::list<double>>(name);
209 (instance)->*mp = (instance2)->*mp;
210 }
211 catch (const std::runtime_error&) {
212 try {
213 long C::* mp = member<long>(name);
214 (instance)->*mp = (instance2)->*mp;
215 }
216 catch (const std::runtime_error&) {
217 // if not found throw error
218 throw std::runtime_error("Unknown member " + name);
219 }
220 }
221 }
222 }
223 }
224 }
225 }
226 }
227 }
228
229 template <typename C>
230 template <typename T>
231 T Published<C>::get(const C* instance, const std::string& name) const
232 {
233 // pointer to member
234 T C::* mp = member<T>(name);
235 return (instance)->*mp;
236 }
237
238 template<typename C>
239 template<typename T>
240 T C::* Published<C>::member(const std::string& name) const
241 {
242 AttributeMap<T>& m = attribute_map<T>();
243 typename AttributeMap<T>::const_iterator it=m.find(name);
244 if (it == m.end()) {
245 // if not found throw error
246 throw std::runtime_error("Unknown member " + name);
247 } else {
248 return it->second;
249 }
250 }
251
252 template<typename C>
253 template<typename T>
254 typename Published<C>::template AttributeMap<T>& Published<C>::attribute_map() const
255 {
256 // static initialisation for flexibility
257 static AttributeMap<T> m;
258 return m;
259 }
260}
261
262#endif
Representation of arrays used in tokens.
Definition: array.h:40
Class that provides introspection to its members.
Definition: published.h:47
void set(C *instance, const std::string &name, GMAD::Array *const &value)
Definition: published.h:147
typename std::unordered_map< std::string, T C::* > AttributeMap
Define AttributeMap of string and class member pointer.
Definition: published.h:69
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:172
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:92
void set(C *instance, const std::string &name, const T &value)
Definition: published.h:135
std::set< std::string > allNames
A cache of all names defined through publish().
Definition: published.h:85
T C::* member(const std::string &name) const
Access to member pointer.
Definition: published.h:240
void set(C *instance, const std::string &name, double value)
Definition: published.h:99
T get(const C *instance, const std::string &name) const
Get method for class C.
Definition: published.h:231
Parser namespace for GMAD language. Combination of Geant4 and MAD.