COVISE Core
message_macros.h
Go to the documentation of this file.
1#ifndef MESSAGE_MACROS_H
2#define MESSAGE_MACROS_H
3
4#include "message_types.h"
5#include <cassert>
6#include <cstring>
7#include <memory>
8#include <string>
9#include <util/tryPrint.h>
10
11namespace covise
12{
13 class TokenBuffer;
14 class MessageSenderInterface;
15 class Message;
16
17 namespace detail
18 {
19 template <typename T>
20 bool equals(const T &t1, const T &t2)
21 {
22 return t1 == t2;
23 }
24 //for char* nullptr is equal to empty string
25 template <>
26 inline bool equals<char const *>(const char *const &t1, const char *const &t2)
27 {
28 if (!t1)
29 {
30 return !t2 || !strcmp(t2, "");
31 }
32 if (!t2)
33 {
34 return !t1 || !strcmp(t1, "");
35 }
36 return !strcmp(t1, t2);
37 }
38 struct Dummy
39 {
40 };
41
42 inline Dummy typeCheck(int msgType, int classType)
43 {
44 if (msgType != classType)
45 throw std::runtime_error("Type mismatch in message_macros: msg type " + std::to_string(msgType) + " , class type " + std::to_string(classType));
46 return Dummy{};
47 }
48
49 template <class T, class Enable = void>
51 {
52 typedef const T &RetVal;
53 }; // primary template
54
55 template <class T>
56 struct ValueOrRef<T, typename std::enable_if<std::is_arithmetic<T>::value || std::is_pointer<T>::value>::type>
57 {
58 typedef T RetVal;
59 };
60
61 enum class MessageSyle
62 {
63 Primary,
65 };
66
67 } //detail
68
69} // namespace covise
70//helper macros
71//----------------------------------------------------------------------------------------------------------------------------------------------
72//EXPAND needed for MSVC
73#define EXPAND(x) x
74
75#define STOP_RECURSION()
76
77#define CAT(A, B) A##B
78#define SELECT(NAME, NUM) CAT(NAME##_, NUM)
79
80#define GET_COUNT(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, COUNT, ...) COUNT
81#define VA_SIZE(...) EXPAND(GET_COUNT(__VA_ARGS__, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 09, 08, 07, 06, 05, 04, 03, 02, 01))
82
83#define VA_SELECT(NAME, ...) \
84 EXPAND(SELECT(NAME, EXPAND(VA_SIZE(__VA_ARGS__)))) \
85 (__VA_ARGS__)
86
87#define MY_OVERLOADED(...) EXPAND(VA_SELECT(MY_OVERLOADED, __VA_ARGS__))
88
89#define MY_OVERLOADED_01(ClassName, MacroName, MacroNameLast, _1) STOP_RECURSION()
90#define MY_OVERLOADED_03(ClassName, MacroName, MacroNameLast, _1, _2, _3) STOP_RECURSION()
91#define MY_OVERLOADED_05(ClassName, MacroName, MacroNameLast, _1, _2, _3, _4, _5) STOP_RECURSION()
92#define MY_OVERLOADED_07(ClassName, MacroName, MacroNameLast, _1, _2, _3, _4, _5, _6, _7) STOP_RECURSION()
93#define MY_OVERLOADED_09(ClassName, MacroName, MacroNameLast, _1, _2, _3, _4, _5, _6, _7, _8, _9) STOP_RECURSION()
94#define MY_OVERLOADED_11(ClassName, MacroName, MacroNameLast, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11) STOP_RECURSION()
95#define MY_OVERLOADED_13(ClassName, MacroName, MacroNameLast, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13) STOP_RECURSION()
96#define MY_OVERLOADED_15(ClassName, MacroName, MacroNameLast, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15) STOP_RECURSION()
97#define MY_OVERLOADED_17(ClassName, MacroName, MacroNameLast, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17) STOP_RECURSION()
98#define MY_OVERLOADED_19(ClassName, MacroName, MacroNameLast, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19) STOP_RECURSION()
99#define MY_OVERLOADED_21(ClassName, MacroName, MacroNameLast, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21) STOP_RECURSION()
100#define MY_OVERLOADED_23(ClassName, MacroName, MacroNameLast, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23) STOP_RECURSION()
101#define MY_OVERLOADED_25(ClassName, MacroName, MacroNameLast, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25) STOP_RECURSION()
102#define MY_OVERLOADED_27(ClassName, MacroName, MacroNameLast, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27) STOP_RECURSION()
103
104#define MY_OVERLOADED_02(MacroName, MacroNameLast, T00, N00) MacroNameLast(T00, N00)
105#define MY_OVERLOADED_04(MacroName, MacroNameLast, T00, N00, T01, N01) MacroName(T00, N00) MY_OVERLOADED_02(MacroName, MacroNameLast, T01, N01)
106#define MY_OVERLOADED_06(MacroName, MacroNameLast, T00, N00, T01, N01, T02, N02) MacroName(T00, N00) MY_OVERLOADED_04(MacroName, MacroNameLast, T01, N01, T02, N02)
107#define MY_OVERLOADED_08(MacroName, MacroNameLast, T00, N00, T01, N01, T02, N02, T03, N03) MacroName(T00, N00) MY_OVERLOADED_06(MacroName, MacroNameLast, T01, N01, T02, N02, T03, N03)
108#define MY_OVERLOADED_10(MacroName, MacroNameLast, T00, N00, T01, N01, T02, N02, T03, N03, N04, T04) MacroName(T00, N00) MY_OVERLOADED_08(MacroName, MacroNameLast, T01, N01, T02, N02, T03, N03, N04, T04)
109#define MY_OVERLOADED_12(MacroName, MacroNameLast, T00, N00, T01, N01, T02, N02, T03, N03, N04, T04, T05, N05) MacroName(T00, N00) MY_OVERLOADED_10(MacroName, MacroNameLast, T01, N01, T02, N02, T03, N03, N04, T04, T05, N05)
110#define MY_OVERLOADED_14(MacroName, MacroNameLast, T00, N00, T01, N01, T02, N02, T03, N03, N04, T04, T05, N05, T06, N06) MacroName(T00, N00) MY_OVERLOADED_12(MacroName, MacroNameLast, T01, N01, T02, N02, T03, N03, N04, T04, T05, N05, T06, N06)
111#define MY_OVERLOADED_16(MacroName, MacroNameLast, T00, N00, T01, N01, T02, N02, T03, N03, N04, T04, T05, N05, T06, N06, T07, N07) MacroName(T00, N00) MY_OVERLOADED_14(MacroName, MacroNameLast, T01, N01, T02, N02, T03, N03, N04, T04, T05, N05, T06, N06, T07, N07)
112#define MY_OVERLOADED_18(MacroName, MacroNameLast, T00, N00, T01, N01, T02, N02, T03, N03, N04, T04, T05, N05, T06, N06, T07, N07, T08, N08) MacroName(T00, N00) MY_OVERLOADED_16(MacroName, MacroNameLast, T01, N01, T02, N02, T03, N03, N04, T04, T05, N05, T06, N06, T07, N07, T08, N08)
113#define MY_OVERLOADED_20(MacroName, MacroNameLast, T00, N00, T01, N01, T02, N02, T03, N03, N04, T04, T05, N05, T06, N06, T07, N07, T08, N08, T09, N09) MacroName(T00, N00) MY_OVERLOADED_18(MacroName, MacroNameLast, T01, N01, T02, N02, T03, N03, N04, T04, T05, N05, T06, N06, T07, N07, T08, N08, T09, N09)
114#define MY_OVERLOADED_22(MacroName, MacroNameLast, T00, N00, T01, N01, T02, N02, T03, N03, N04, T04, T05, N05, T06, N06, T07, N07, T08, N08, T09, N09, T10, N10) MacroName(T00, N00) MY_OVERLOADED_20(MacroName, MacroNameLast, T01, N01, T02, N02, T03, N03, N04, T04, T05, N05, T06, N06, T07, N07, T08, N08, T09, N09, T10, N10)
115#define MY_OVERLOADED_24(MacroName, MacroNameLast, T00, N00, T01, N01, T02, N02, T03, N03, N04, T04, T05, N05, T06, N06, T07, N07, T08, N08, T09, N09, T10, N10, T11, N11) MacroName(T00, N00) MY_OVERLOADED_22(MacroName, MacroNameLast, T01, N01, T02, N02, T03, N03, N04, T04, T05, N05, T06, N06, T07, N07, T08, N08, T09, N09, T10, N10, T11, N11)
116#define MY_OVERLOADED_26(MacroName, MacroNameLast, T00, N00, T01, N01, T02, N02, T03, N03, N04, T04, T05, N05, T06, N06, T07, N07, T08, N08, T09, N09, T10, N10, T11, N11, T12, N12) MacroName(T00, N00) MY_OVERLOADED_24(MacroName, MacroNameLast, T01, N01, T02, N02, T03, N03, N04, T04, T05, N05, T06, N06, T07, N07, T08, N08, T09, N09, T10, N10, T11, N11, T12, N12)
117
118#define ACCESSOR(type, name) \
119 typename covise::detail::ValueOrRef<type>::RetVal name() const { return CAT(m_, name); }\
120
121#define DECLARATION(type, name) \
122 type CAT(m_, name);
123
124#define CONSTRUCTOR_ELEMENT_LAST(type, name) \
125 typename covise::detail::ValueOrRef<type>::RetVal name
126
127#define CONSTRUCTOR_ELEMENT(type, name) \
128 CONSTRUCTOR_ELEMENT_LAST(type, name),
129
130#define CONSTRUCTOR_INITIALIZER_ELEM_LAST(type, name) \
131 CAT(m_, name)(name)
132
133#define CONSTRUCTOR_INITIALIZER_ELEM(type, name) \
134 CONSTRUCTOR_INITIALIZER_ELEM_LAST(type, name),
135
136
137#define CONSTRUCTOR_INITIALIZER_TB_LAST(type, name) \
138 CAT(m_, name)(covise::detail::get<type>(tb))
139
140#define CONSTRUCTOR_INITIALIZER_TB(type, name) \
141 CONSTRUCTOR_INITIALIZER_TB_LAST(type, name),
142
143#define FILL_TOKENBUFFER(type, name) \
144 << msg.name()
145
146#define TAKE_FROM_TOKENBUFFER(type, name) \
147 >> msg.CAT(m_, name)
148
149#define PRINT_CLASS(type, name) \
150 os << #name << ": "; \
151 covise::tryPrintWithError(os, msg.name(), #type, " is not printable"); \
152 os << ", ";
153
154#define CHECK_EQUALITY(type, name) \
155 covise::detail::equals(c1.name(), c2.name()) &&
156
157//----------------------------------------------------------------------------------------------------------------------------------------------
158
159#define DECL_TB_SERIALIZABLE_STRUCT(ClassName, export, ...) \
160 struct export ClassName{ \
161 EXPAND(MY_OVERLOADED(DECLARATION, DECLARATION, __VA_ARGS__)) \
162 EXPAND(MY_OVERLOADED(ACCESSOR, ACCESSOR, __VA_ARGS__))}; \
163 export covise::TokenBuffer &operator<<(covise::TokenBuffer &tb, const ClassName &msg); \
164 export covise::TokenBuffer &operator>>(covise::TokenBuffer &tb, ClassName &msg); \
165 export std::ostream &operator<<(std::ostream &os, const ClassName &msg);
166
167#define IMPL_TB_SERIALIZABLE_STRUCT(ClassName, ...) \
168 covise::TokenBuffer &operator<<(covise::TokenBuffer &tb, const ClassName &msg) \
169 { \
170 tb EXPAND(MY_OVERLOADED(FILL_TOKENBUFFER, FILL_TOKENBUFFER, __VA_ARGS__)); \
171 return tb; \
172 } \
173 covise::TokenBuffer &operator>>(covise::TokenBuffer &tb, ClassName &msg) \
174 { \
175 tb EXPAND(MY_OVERLOADED(TAKE_FROM_TOKENBUFFER, TAKE_FROM_TOKENBUFFER, __VA_ARGS__)); \
176 return tb; \
177 } \
178 std::ostream &operator<<(std::ostream &os, const ClassName &msg) \
179 { \
180 os << #ClassName << ":" << std::endl; \
181 EXPAND(MY_OVERLOADED(PRINT_CLASS, PRINT_CLASS, __VA_ARGS__)); \
182 os << std::endl; \
183 return os; \
184 }
185
186//use in header files to declare a type that can be sent and received via messages
187//ClassName: message type without COVISE_MESSAGE_
188//export: the export macro to use
189//...: pairs of typename , value name. Used types must provide stream operators for TokenBuffer
190//implements a class with the given members.
191//use sendCoviseMessage function to send the message
192//receive the message by constructing this class from the message
193//also implements operator<< for ostream and tokenbuffer and operator== (for const char* nullptr =="")
194#define DECL_MESSAGE_CLASS(ClassName, export, ...) \
195 struct export ClassName \
196 { \
197 static constexpr covise::detail::MessageSyle Style = covise::detail::MessageSyle::Primary; \
198 ClassName(EXPAND(MY_OVERLOADED(CONSTRUCTOR_ELEMENT, CONSTRUCTOR_ELEMENT_LAST, __VA_ARGS__))); \
199 explicit ClassName(const covise::Message &msg); \
200 covise::Message createMessage() const; \
201 EXPAND(MY_OVERLOADED(ACCESSOR, ACCESSOR, __VA_ARGS__)) \
202 \
203 private: \
204 EXPAND(MY_OVERLOADED(DECLARATION, DECLARATION, __VA_ARGS__)) \
205 ClassName(covise::detail::Dummy, covise::TokenBuffer &&tb); \
206 }; \
207 export covise::TokenBuffer &operator<<(covise::TokenBuffer &tb, const ClassName &msg); \
208 export std::ostream &operator<<(std::ostream &tb, const ClassName &exe); \
209 export bool sendCoviseMessage(const ClassName &msg, const covise::MessageSenderInterface &sender); \
210 export bool operator==(const ClassName &c1, const ClassName &c2);
211
212//use in .cpp with same arguments as DECL_MESSAGE_CLASS exept the export argument
213#define IMPL_MESSAGE_CLASS(ClassName, ...) \
214 ClassName::ClassName(EXPAND(MY_OVERLOADED(CONSTRUCTOR_ELEMENT, CONSTRUCTOR_ELEMENT_LAST, __VA_ARGS__))) \
215 : EXPAND(MY_OVERLOADED(CONSTRUCTOR_INITIALIZER_ELEM, CONSTRUCTOR_INITIALIZER_ELEM_LAST, __VA_ARGS__)) {} \
216 ClassName::ClassName(const covise::Message &msg) : ClassName(covise::detail::typeCheck(msg.type, covise::CAT(COVISE_MESSAGE_, ClassName)), covise::TokenBuffer{&msg}) {} \
217 ClassName::ClassName(covise::detail::Dummy, covise::TokenBuffer &&tb) \
218 : EXPAND(MY_OVERLOADED(CONSTRUCTOR_INITIALIZER_TB, CONSTRUCTOR_INITIALIZER_TB_LAST, __VA_ARGS__)) {} \
219 covise::Message ClassName::createMessage() const \
220 { \
221 covise::TokenBuffer tb; \
222 tb << *this; \
223 covise::Message m{tb}; \
224 m.type = covise::CAT(COVISE_MESSAGE_, ClassName); \
225 return m; \
226 } \
227 covise::TokenBuffer &operator<<(covise::TokenBuffer &tb, const ClassName &msg) \
228 { \
229 tb EXPAND(MY_OVERLOADED(FILL_TOKENBUFFER, FILL_TOKENBUFFER, __VA_ARGS__)); \
230 return tb; \
231 } \
232 bool sendCoviseMessage(const ClassName &msg, const covise::MessageSenderInterface &sender) \
233 { \
234 auto m = msg.createMessage(); \
235 return sender.send(&m); \
236 } \
237 std::ostream &operator<<(std::ostream &os, const ClassName &msg) \
238 { \
239 os << #ClassName << ":" << std::endl; \
240 EXPAND(MY_OVERLOADED(PRINT_CLASS, PRINT_CLASS, __VA_ARGS__)); \
241 os << std::endl; \
242 return os; \
243 } \
244 bool operator==(const ClassName &c1, const ClassName &c2) \
245 { \
246 return EXPAND(MY_OVERLOADED(CHECK_EQUALITY, CHECK_EQUALITY, __VA_ARGS__)) true; \
247 }
248
249#define DECL_SUB_MESSAGE_CLASS_DETAIL(ClassName, FullClassName, EnumClass, EnumType, export, ...) \
250 struct export FullClassName : public ClassName \
251 { \
252 friend struct ClassName; \
253 static constexpr covise::detail::MessageSyle Style = covise::detail::MessageSyle::SubMessage; \
254 typedef ClassName Base; \
255 explicit FullClassName(EXPAND(MY_OVERLOADED(CONSTRUCTOR_ELEMENT, CONSTRUCTOR_ELEMENT_LAST, __VA_ARGS__))); \
256 FullClassName(const FullClassName &) = delete; \
257 FullClassName(FullClassName &&) = default; \
258 FullClassName &operator=(const FullClassName &) = delete; \
259 FullClassName &operator=(FullClassName &&) = default; \
260 ~FullClassName() = default; \
261 covise::Message createMessage() const; \
262 EXPAND(MY_OVERLOADED(ACCESSOR, ACCESSOR, __VA_ARGS__)) \
263 \
264 static const EnumClass subType = EnumClass::EnumType; \
265 private: \
266 EXPAND(MY_OVERLOADED(DECLARATION, DECLARATION, __VA_ARGS__)) \
267 explicit FullClassName(const covise::Message &msg); \
268 explicit FullClassName(covise::detail::Dummy, covise::TokenBuffer &&tb); \
269 }; \
270 export covise::TokenBuffer &operator<<(covise::TokenBuffer &tb, const FullClassName &msg); \
271 export std::ostream &operator<<(std::ostream &tb, const FullClassName &exe); \
272 export bool sendCoviseMessage(const FullClassName &msg, const covise::MessageSenderInterface &sender);
273
274#define DECL_SUB_MESSAGE_CLASS(ClassName, EnumClass, EnumType, export, ...) \
275 DECL_SUB_MESSAGE_CLASS_DETAIL(ClassName, ClassName##_##EnumType, EnumClass, EnumType, export, __VA_ARGS__)
276
277#define IMPL_SUB_MESSAGE_CLASS_DETAIL(ClassName, FullClassName, EnumClass, EnumType, ...) \
278 FullClassName::FullClassName(EXPAND(MY_OVERLOADED(CONSTRUCTOR_ELEMENT, CONSTRUCTOR_ELEMENT_LAST, __VA_ARGS__))) \
279 : ClassName(EnumClass::EnumType), EXPAND(MY_OVERLOADED(CONSTRUCTOR_INITIALIZER_ELEM, CONSTRUCTOR_INITIALIZER_ELEM_LAST, __VA_ARGS__)) {} \
280 FullClassName::FullClassName(const covise::Message &msg) : FullClassName(covise::detail::typeCheck(msg.type, covise::CAT(COVISE_MESSAGE_, ClassName)), covise::TokenBuffer{&msg}) {} \
281 FullClassName::FullClassName(covise::detail::Dummy, covise::TokenBuffer &&tb) \
282 : ClassName(static_cast<EnumClass>(covise::detail::get<int>(tb))), EXPAND(MY_OVERLOADED(CONSTRUCTOR_INITIALIZER_TB, CONSTRUCTOR_INITIALIZER_TB_LAST, __VA_ARGS__)) {} \
283 covise::Message FullClassName::createMessage() const \
284 { \
285 covise::TokenBuffer tb; \
286 tb << *this; \
287 covise::Message m{tb}; \
288 m.type = covise::CAT(COVISE_MESSAGE_, ClassName); \
289 return m; \
290 } \
291 covise::TokenBuffer &operator<<(covise::TokenBuffer &tb, const FullClassName &msg) \
292 { \
293 tb << static_cast<int>(msg.type) EXPAND(MY_OVERLOADED(FILL_TOKENBUFFER, FILL_TOKENBUFFER, __VA_ARGS__)); \
294 return tb; \
295 } \
296 bool sendCoviseMessage(const FullClassName &msg, const covise::MessageSenderInterface &sender) \
297 { \
298 auto m = msg.createMessage(); \
299 return sender.send(&m); \
300 } \
301 std::ostream &operator<<(std::ostream &os, const FullClassName &msg) \
302 { \
303 os << #FullClassName << ":" << std::endl; \
304 EXPAND(MY_OVERLOADED(PRINT_CLASS, PRINT_CLASS, __VA_ARGS__)); \
305 os << std::endl; \
306 return os; \
307 }
308
309#define IMPL_SUB_MESSAGE_CLASS(ClassName, EnumClass, EnumType, ...) \
310 IMPL_SUB_MESSAGE_CLASS_DETAIL(ClassName, ClassName##_##EnumType, EnumClass, EnumType, __VA_ARGS__)
311
312#define DECL_MESSAGE_WITH_SUB_CLASSES(ClassName, EnumClass, export) \
313 struct export ClassName \
314 { \
315 ClassName(const covise::Message &msg); \
316 virtual ~ClassName() = default; \
317 const EnumClass type; \
318 static constexpr int MessageType = covise::CAT(COVISE_MESSAGE_, ClassName); \
319 template <typename Derived> \
320 const Derived &unpackOrCast() const \
321 { \
322 covise::detail::typeCheck(static_cast<int>(Derived::subType), static_cast<int>(type)); \
323 if (!m_msg) \
324 { \
325 return *dynamic_cast<const Derived *>(this); \
326 } \
327 if (!m_subMsg) \
328 { \
329 m_subMsg.reset(new Derived(*m_msg)); \
330 } \
331 return *dynamic_cast<const Derived *>(m_subMsg.get()); \
332 } \
333 template <typename Derived> \
334 Derived createDerived() const \
335 { \
336 assert(m_msg); \
337 return Derived{*m_msg}; \
338 } \
339 \
340 protected: \
341 ClassName(EnumClass); \
342 \
343 private: \
344 ClassName(covise::detail::Dummy, covise::TokenBuffer &&tb, const covise::Message &msg); \
345 const covise::Message *m_msg = nullptr; \
346 mutable std::shared_ptr<ClassName> m_subMsg; \
347 };
348
349#define IMPL_MESSAGE_WITH_SUB_CLASSES(ClassName, EnumClass) \
350 ClassName::ClassName(const covise::Message &msg) : ClassName(covise::detail::typeCheck(msg.type, covise::CAT(COVISE_MESSAGE_, ClassName)), covise::TokenBuffer(&msg), msg) {} \
351 ClassName::ClassName(covise::detail::Dummy, covise::TokenBuffer &&tb, const covise::Message &msg) \
352 : type(static_cast<EnumClass>(covise::detail::get<int>(tb))), m_msg(&msg) {} \
353 ClassName::ClassName(EnumClass t) \
354 : type(t) \
355 { \
356 }
357
358#endif // ! MESSAGE_MACROS_H
GLuint GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat t1
Definition: khronos-glext.h:13144
GLenum type
Definition: khronos-glext.h:6279
list of all chemical elements
Definition: coConfig.h:27
Dummy typeCheck(int msgType, int classType)
Definition: message_macros.h:42
bool equals< char const * >(const char *const &t1, const char *const &t2)
Definition: message_macros.h:26
bool equals(const T &t1, const T &t2)
Definition: message_macros.h:20
MessageSyle
Definition: message_macros.h:62
Definition: message_macros.h:39
Definition: message_macros.h:51
const T & RetVal
Definition: message_macros.h:52