ClassMemberInfo.h
Go to the documentation of this file.
1/*
2 * This file is part of ArmarX.
3 *
4 * ArmarX is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 *
8 * ArmarX is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * @package RobotAPI::RobotUnit
17 * @author Raphael Grimm ( raphael dot grimm at kit dot edu )
18 * @date 2017
19 * @copyright http://www.gnu.org/licenses/gpl-2.0.txt
20 * GNU General Public License
21 */
22#pragma once
23
25
27
29{
30 /**
31 * @brief
32 */
33 template <class CommonBaseT, class ClassT>
35 {
36 using ClassType = ClassT;
37 using CommonBaseType = CommonBaseT;
38 static_assert(std::is_base_of<CommonBaseType, ClassType>::value,
39 "The class has to inherit the common base class");
41 template <class T>
44
46
47 /// @brief add a member variable of the current class
48 template <class MemberType>
50 const std::string& name);
51
52 /// @brief add all variables of a base class of the current class
53 template <class BaseClassType>
55
56 /// @brief Get the name of the current class
57 static const std::string& GetClassName();
58 /// @brief Get all entries for member variables
60 static std::size_t GetNumberOfDataFields();
61 static void GetDataFieldAs(const ClassType* ptr, std::size_t i, bool& out);
62 static void GetDataFieldAs(const ClassType* ptr, std::size_t i, Ice::Byte& out);
63 static void GetDataFieldAs(const ClassType* ptr, std::size_t i, Ice::Short& out);
64 static void GetDataFieldAs(const ClassType* ptr, std::size_t i, Ice::Int& out);
65 static void GetDataFieldAs(const ClassType* ptr, std::size_t i, Ice::Long& out);
66 static void GetDataFieldAs(const ClassType* ptr, std::size_t i, Ice::Float& out);
67 static void GetDataFieldAs(const ClassType* ptr, std::size_t i, Ice::Double& out);
68 static void GetDataFieldAs(const ClassType* ptr, std::size_t i, std::string& out);
69 static const std::type_info& GetDataFieldType(std::size_t i);
70 static std::vector<std::string> GetDataFieldNames();
71
72 static std::map<std::string, VariantBasePtr> ToVariants(const IceUtil::Time& timestamp,
73 const CommonBaseT* ptr);
74
75 private:
76 template <class T>
77 static auto
78 MakeConverter()
79 {
81 std::vector<std::function<void(const ClassType*, T&)>> functions;
82
83 for (std::size_t idxEntr = 0; idxEntr < GetEntries().size(); ++idxEntr)
84 {
85 for (std::size_t idxField = 0;
86 idxField < GetEntries().at(idxEntr).getNumberOfFields();
87 ++idxField)
88 {
89 functions.emplace_back(
90 [idxEntr, idxField](const ClassType* classptr, T& out)
91 {
92 const Entry& e = GetEntries().at(idxEntr);
93 e.getDataFieldAs(idxField, classptr, out);
94 });
95 }
96 }
97 ARMARX_CHECK_EQUAL(functions.size(), GetNumberOfDataFields());
98 return functions;
99 }
100
101 private:
102 KeyValueVector<std::string, Entry> entries;
103 std::set<std::string> addedBases;
104 };
105} // namespace armarx::introspection
106
107//implementation
108namespace armarx::introspection
109{
110 template <class CommonBaseT, class ClassT>
111 template <class MemberType>
112 typename ClassMemberInfo<CommonBaseT, ClassT>::template EntryConfigurator<ClassT>
114 const std::string& name)
115 {
117 ARMARX_CHECK_EQUAL(entries.count(name), 0) << name;
118 entries.add(name, Entry(name, ptr));
119 return entries.at(name);
120 }
121
122 template <class CommonBaseT, class ClassT>
123 template <class BaseClassType>
124 void
126 {
128 if (std::is_same<BaseClassType, CommonBaseType>::value)
129 {
130 return;
131 }
132 static_assert(std::is_base_of<CommonBaseType, BaseClassType>::value,
133 "The base class has to inherit the common base class");
134 static_assert(std::is_base_of<BaseClassType, ClassType>::value,
135 "The base class has to be a base class");
136 static_assert(!std::is_same<BaseClassType, ClassType>::value,
137 "The base class has must not be the class");
138
139 std::set<std::string> basesAddedInCall;
141 {
142 return;
143 }
145 {
146 if (!addedBases.count(e.getClassName()))
147 {
148 ARMARX_CHECK_EXPRESSION(!entries.count(e.getMemberName()))
149 << "Adding the base class '" << GetTypeString<BaseClassType>()
150 << "' adds an entry for the member '" << e.getMemberName()
151 << "' which already was added by class '"
152 << entries.at(e.getMemberName()).getClassName() << "'";
153 basesAddedInCall.emplace(e.getClassName());
154 entries.add(e.getMemberName(), e);
155 }
156 }
157 addedBases.insert(basesAddedInCall.begin(), basesAddedInCall.end());
158 }
159
160 template <class CommonBaseT, class ClassT>
161 std::vector<std::string>
163 {
165 std::vector<std::string> dataFieldNames;
166 dataFieldNames.reserve(GetNumberOfDataFields());
167 for (const Entry& e : GetEntries().values())
168 {
169 for (std::size_t i = 0; i < e.getNumberOfFields(); ++i)
170 {
171 dataFieldNames.emplace_back(e.getFieldName(i));
172 }
173 }
174 ARMARX_CHECK_EQUAL(GetNumberOfDataFields(), dataFieldNames.size());
175 return dataFieldNames;
176 }
177
178 template <class CommonBaseT, class ClassT>
179 std::map<std::string, VariantBasePtr>
181 const CommonBaseT* ptr)
182 {
184 std::map<std::string, VariantBasePtr> result;
185 for (const auto& e : GetEntries().values())
186 {
187 auto newMap = e.toVariants(timestamp, ptr);
188 for (auto& elem : newMap)
189 {
190 if (result.count(elem.first))
191 {
192 throw std::invalid_argument{
193 "mergeMaps: newMap would override values from oldMap"};
194 }
195 }
196 for (auto& elem : newMap)
197 {
198 result[elem.first] = elem.second;
199 }
200 //mergeMaps(result, , MergeMapsMode::OverrideNoValues);
201 }
202 return result;
203 }
204
205 template <class CommonBaseT, class ClassT>
208 {
209 static const ClassMemberInfo<CommonBaseT, ClassT> i = ClassT::GetClassMemberInfo();
210 return i;
211 }
212
213 template <class CommonBaseT, class ClassT>
214 const std::string&
219
220 template <class CommonBaseT, class ClassT>
226
227 template <class CommonBaseT, class ClassT>
228 std::size_t
230 {
232 static const std::size_t numberOfDataFields = []
233 {
234 std::size_t n = 0;
235 for (const Entry& e : GetEntries().values())
236 {
237 n += e.getNumberOfFields();
238 }
239 return n;
240 }();
241 return numberOfDataFields;
242 }
243
244 template <class CommonBaseT, class ClassT>
245 void
247 std::size_t i,
248 bool& out)
249 {
251 static const auto convert = MakeConverter<bool>();
253 convert.at(i)(ptr, out);
254 }
255
256 template <class CommonBaseT, class ClassT>
257 void
259 std::size_t i,
260 Ice::Byte& out)
261 {
263 static const auto convert = MakeConverter<Ice::Byte>();
265 convert.at(i)(ptr, out);
266 }
267
268 template <class CommonBaseT, class ClassT>
269 void
271 std::size_t i,
272 Ice::Short& out)
273 {
275 static const auto convert = MakeConverter<Ice::Short>();
277 convert.at(i)(ptr, out);
278 }
279
280 template <class CommonBaseT, class ClassT>
281 void
283 std::size_t i,
284 Ice::Int& out)
285 {
287 static const auto convert = MakeConverter<Ice::Int>();
289 convert.at(i)(ptr, out);
290 }
291
292 template <class CommonBaseT, class ClassT>
293 void
295 std::size_t i,
296 Ice::Long& out)
297 {
299 static const auto convert = MakeConverter<Ice::Long>();
301 convert.at(i)(ptr, out);
302 }
303
304 template <class CommonBaseT, class ClassT>
305 void
307 std::size_t i,
308 Ice::Float& out)
309 {
311 static const auto convert = MakeConverter<Ice::Float>();
313 convert.at(i)(ptr, out);
314 }
315
316 template <class CommonBaseT, class ClassT>
317 void
319 std::size_t i,
320 Ice::Double& out)
321 {
323 static const auto convert = MakeConverter<Ice::Double>();
325 convert.at(i)(ptr, out);
326 }
327
328 template <class CommonBaseT, class ClassT>
329 void
331 std::size_t i,
332 std::string& out)
333 {
335 static const auto convert = MakeConverter<std::string>();
337 convert.at(i)(ptr, out);
338 }
339
340 template <class CommonBaseT, class ClassT>
341 const std::type_info&
343 {
345 static const auto convert = []
346 {
347 std::vector<const std::type_info*> data;
348
349 for (std::size_t idxEntr = 0; idxEntr < GetEntries().size(); ++idxEntr)
350 {
351 const Entry& e = GetEntries().at(idxEntr);
352 for (std::size_t idxField = 0;
353 idxField < GetEntries().at(idxEntr).getNumberOfFields();
354 ++idxField)
355 {
356 data.emplace_back(&e.getFieldTypeId(idxField));
357 }
358 }
360 return data;
361 }();
363 return *convert.at(i);
364 }
365} // namespace armarx::introspection
std::string timestamp()
This class is pretty much similar to a map.
#define ARMARX_CHECK_EXPRESSION(expression)
This macro evaluates the expression and if it turns out to be false it will throw an ExpressionExcept...
#define ARMARX_CHECK_LESS(lhs, rhs)
This macro evaluates whether lhs is less (<) than rhs and if it turns out to be false it will throw a...
#define ARMARX_CHECK_EQUAL(lhs, rhs)
This macro evaluates whether lhs is equal (==) rhs and if it turns out to be false it will throw an E...
std::string GetTypeString(const std::type_info &tinf, bool withoutNamespaceSpecifier=false)
armem::articulated_object::ArticulatedObject convert(const VirtualRobot::Robot &obj, const armem::Time &timestamp)
void getDataFieldAs(std::size_t i, const CommonBaseType *ptr, bool &out) const
const std::type_info & getFieldTypeId(std::size_t i) const
static void GetDataFieldAs(const ClassType *ptr, std::size_t i, std::string &out)
void addBaseClass()
add all variables of a base class of the current class
static void GetDataFieldAs(const ClassType *ptr, std::size_t i, Ice::Short &out)
static const std::string & GetClassName()
Get the name of the current class.
static void GetDataFieldAs(const ClassType *ptr, std::size_t i, bool &out)
static void GetDataFieldAs(const ClassType *ptr, std::size_t i, Ice::Byte &out)
static std::vector< std::string > GetDataFieldNames()
static const std::type_info & GetDataFieldType(std::size_t i)
EntryConfigurator< ClassType > addMemberVariable(MemberType ClassType::*ptr, const std::string &name)
add a member variable of the current class
static void GetDataFieldAs(const ClassType *ptr, std::size_t i, Ice::Double &out)
static std::map< std::string, VariantBasePtr > ToVariants(const IceUtil::Time &timestamp, const CommonBaseT *ptr)
introspection::ClassMemberInfoEntry< CommonBaseType > Entry
introspection::ClassMemberInfoEntryConfigurator< CommonBaseType, T > EntryConfigurator
static void GetDataFieldAs(const ClassType *ptr, std::size_t i, Ice::Int &out)
static void GetDataFieldAs(const ClassType *ptr, std::size_t i, Ice::Float &out)
static const KeyValueVector< std::string, Entry > & GetEntries()
Get all entries for member variables.
static const ClassMemberInfo< CommonBaseT, ClassT > & GetInstance()
static void GetDataFieldAs(const ClassType *ptr, std::size_t i, Ice::Long &out)
#define ARMARX_TRACE
Definition trace.h:77