rcolyer.net
RC Lib  Version 202403231100
Macros.h
Go to the documentation of this file.
1 /////////////////////////////////////////////////////////////////////
2 //
3 // RC Library, (c) 2012-2015, Ryan A. Colyer
4 // Distributed under the Boost Software License, v1.0. (LICENSE.txt)
5 //
6 /// \file Macros.h
7 /// Provides a set of convenience macros for metaprogramming
8 /// and debugging.
9 /** Note: RC_EMPTY, RC_ARGS_NUM, RC_ARGS_EACH, RC_ARGS_BET,
10  * RC_ARGS_LIST, and RC_DEBOUT require each of their parameters to
11  * begin with a letter, number, or underscore.
12  */
13 /////////////////////////////////////////////////////////////////////
14 
15 #ifndef RC_MACROS_H
16 #define RC_MACROS_H
17 
18 #include "RCconfig.h"
19 #ifdef unix
20 #include <dlfcn.h>
21 #elif defined(WIN32)
22 #include <winsock2.h>
23 #include <windows.h>
24 #endif
25 
26 namespace RC {
27 
28 /// \def RC_NOP
29 /// Evaluates to whatever is passed in. Does no operation.
30 #define RC_NOP(...) __VA_ARGS__
31 
32 /// @cond UNDOC
33 #define RC_CAT_HELP(a,b) a ## b
34 /// @endcond
35 /// \def RC_CAT
36 /// Concatenates two tokens.
37 #define RC_CAT(a,b) RC_CAT_HELP(a,b)
38 
39 /// @cond UNDOC
40 #define RC_EMPTY_CHECK2(a,b,...) b
41 #define RC_EMPTY_CHECKb(...) RC_EMPTY_CHECK2(__VA_ARGS__)
42 #define RC_EMPTY_CHECK(...) RC_EMPTY_CHECKb(__VA_ARGS__ (),0)
43 #define RC_EMPTY_F1RC_EMPTY_F0() ~,1,
44 #define RC_EMPTY_HELP3(a,b,...) a ## b
45 #define RC_EMPTY_HELP2(...) RC_EMPTY_HELP3(RC_EMPTY_F1, __VA_ARGS__ RC_EMPTY_F0)
46 #define RC_EMPTY_HELPb(x,...) RC_EMPTY_CHECK(x)
47 #define RC_EMPTY_HELP(...) RC_EMPTY_HELPb(__VA_ARGS__)
48 /// @endcond
49 
50 /// \def RC_EMPTY
51 /// Returns 1 if no arguments passed, 0 if arguments are passed.
52 #define RC_EMPTY(...) RC_EMPTY_HELP(RC_EMPTY_HELP2(__VA_ARGS__))
53 
54 
55 /// @cond UNDOC
56 #define RC_ARGNUMCAT_HELPER(a, b) a ## b
57 #define RC_ARGNUMCAT(a, b) RC_ARGNUMCAT_HELPER(a, b)
58 #define RC_ARGS_NUM_HELPER(_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,_29,_30,_31,_32,_33,_34,_35,_36,_37,_38,_39,_40,_41,_42,_43,_44,_45,_46,_47,_48,_49,_50,_51,_52,_53,_54,_55,_56,_57,_58,_59,_60,_61,_62,_63,N,...) N
59 #define RC_ARGS_EVAL1(...) 0
60 #define RC_ARGS_EVAL0(...) RC_ARGS_NUM_HELPER(__VA_ARGS__,63,62,61,60,59,58,57,56,55,54,53,52,51,50,49,48,47,46,45,44,43,42,41,40,39,38,37,36,35,34,33,32,31,30,29,28,27,26,25,24,23,22,21,20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1)
61 /// @endcond
62 
63 /// \def RC_ARGS_NUM
64 /// Returns the number of arguments passed to the macro, from 0 to 63.
65 #define RC_ARGS_NUM(...) RC_ARGNUMCAT(RC_ARGS_EVAL,RC_EMPTY(__VA_ARGS__))(__VA_ARGS__)
66 
67 
68 /// @cond UNDOC
69 #define RC_EV(...) RC_EV1(RC_EV1(RC_EV1(RC_EV1(__VA_ARGS__))))
70 #define RC_EV1(...) RC_EV2(RC_EV2(RC_EV2(RC_EV2(__VA_ARGS__))))
71 #define RC_EV2(...) RC_EV3(RC_EV3(RC_EV3(RC_EV3(__VA_ARGS__))))
72 #define RC_EV3(...) RC_EV4(RC_EV4(RC_EV4(RC_EV4(__VA_ARGS__))))
73 #define RC_EV4(...) __VA_ARGS__
74 
75 #define RC_ARGS_EAT(...)
76 #define RC_ARGS_EACH_HELP_1 RC_ARGS_EAT
77 #define RC_ARGS_EACH_HELP_0 RC_ARGS_EACH_LOOP2 RC_ARGS_EAT() ()
78 #define RC_ARGS_EACH_HELP2(x) RC_ARGS_EACH_HELP_##x
79 #define RC_ARGS_EACH_HELP(x) RC_ARGS_EACH_HELP2(x)
80 #define RC_ARGS_EACH_LOOP(func,x,...) func(x)RC_ARGS_EACH_HELP(RC_EMPTY(__VA_ARGS__)) (func,__VA_ARGS__)
81 #define RC_ARGS_EACH_LOOP2() RC_ARGS_EACH_LOOP
82 /// @endcond
83 
84 /// \def RC_ARGS_EACH
85 /// Does RC_ARGS_EACH(Macro,a,b,c) --> Macro(a)Macro(b)Macro(c), for any
86 /// number of parameters up to 342 or compiler limits.
87 #define RC_ARGS_EACH(Macro,...) RC_EV(RC_ARGS_EACH_HELP(RC_EMPTY(__VA_ARGS__))(Macro,__VA_ARGS__))
88 
89 /// @cond UNDOC
90 #define RC_ARGS_BET_HELP0(func,bet,x,...) func(x)RC_ARGS_EACH(bet func,__VA_ARGS__)
91 #define RC_ARGS_BET_HELP1(func,bet,...)
92 #define RC_ARGS_BET_CAT2(a,b) a##b
93 #define RC_ARGS_BET_CAT(a,b) RC_ARGS_BET_CAT2(a,b)
94 #define RC_ARGS_BET_HELP(func,bet,...) RC_ARGS_BET_CAT(RC_ARGS_BET_HELP,RC_EMPTY(__VA_ARGS__))(func,bet,__VA_ARGS__)
95 /// @endcond
96 
97 /// \def RC_ARGS_BET
98 /// Does RC_ARGS_BET(Func,Between,a,b,c) --> Func(a)Between Func(b)Between
99 /// Func(c)
100 /** For example: cout RC_ARGS_BET(<< int, << ", ", 1.4, 2.5, 3.6); -->
101  * cout << int(1.4) << ", " << int(2.5) << ", " << int(3.5);
102  * @see RC_ARGS_EACH
103  */
104 #define RC_ARGS_BET(func,bet,...) RC_ARGS_BET_HELP(func,bet,__VA_ARGS__)
105 
106 /// @cond UNDOC
107 #define RC_ARGS_LIST_FIRST_1 RC_ARGS_EAT
108 #define RC_ARGS_LIST_FIRST_0 RC_ARGS_LIST_LPFIRST2 RC_ARGS_EAT() ()
109 #define RC_ARGS_LIST_FIRST2(x) RC_ARGS_LIST_FIRST_##x
110 #define RC_ARGS_LIST_FIRST(x) RC_ARGS_LIST_FIRST2(x)
111 #define RC_ARGS_LIST_LPFIRST(func,x,...) func(x)RC_ARGS_LIST_HELP(RC_EMPTY(__VA_ARGS__)) (func,__VA_ARGS__)
112 #define RC_ARGS_LIST_LPFIRST2() RC_ARGS_LIST_LPFIRST
113 #define RC_ARGS_LIST_HELP_1 RC_ARGS_EAT
114 #define RC_ARGS_LIST_HELP_0 RC_ARGS_LIST_LOOP2 RC_ARGS_EAT() ()
115 #define RC_ARGS_LIST_HELP2(x) RC_ARGS_LIST_HELP_##x
116 #define RC_ARGS_LIST_HELP(x) RC_ARGS_LIST_HELP2(x)
117 #define RC_ARGS_LIST_LOOP(func,x,...) ,func(x)RC_ARGS_LIST_HELP(RC_EMPTY(__VA_ARGS__)) (func,__VA_ARGS__)
118 #define RC_ARGS_LIST_LOOP2() RC_ARGS_LIST_LOOP
119 /// @endcond
120 
121 /// \def RC_ARGS_LIST
122 /// Does RC_ARGS_LIST(Func,a,b,c) --> Func(a),Func(b),Func(c)
123 /** @see RC_ARGS_EACH
124  */
125 #define RC_ARGS_LIST(func,...) RC_EV(RC_ARGS_LIST_FIRST(RC_EMPTY(__VA_ARGS__))(func,__VA_ARGS__))
126 
127 /// @cond UNDOC
128 #define RC_ARGS_PAIR_FIRST_1 RC_ARGS_EAT
129 #define RC_ARGS_PAIR_FIRST_0 RC_ARGS_PAIR_LPFIRST2 RC_ARGS_EAT() ()
130 #define RC_ARGS_PAIR_FIRST2(x) RC_ARGS_PAIR_FIRST_##x
131 #define RC_ARGS_PAIR_FIRST(x) RC_ARGS_PAIR_FIRST2(x)
132 #define RC_ARGS_PAIR_LPFIRST(odd,even,x,y,...) odd(x)even(y)RC_ARGS_PAIR_HELP(RC_EMPTY(__VA_ARGS__)) (odd,even,__VA_ARGS__)
133 #define RC_ARGS_PAIR_LPFIRST2() RC_ARGS_PAIR_LPFIRST
134 #define RC_ARGS_PAIR_HELP_1 RC_ARGS_EAT
135 #define RC_ARGS_PAIR_HELP_0 RC_ARGS_PAIR_LOOP2 RC_ARGS_EAT() ()
136 #define RC_ARGS_PAIR_HELP2(x) RC_ARGS_PAIR_HELP_##x
137 #define RC_ARGS_PAIR_HELP(x) RC_ARGS_PAIR_HELP2(x)
138 #define RC_ARGS_PAIR_LOOP(odd,even,x,y,...) ,odd(x)even(y)RC_ARGS_PAIR_HELP(RC_EMPTY(__VA_ARGS__)) (odd,even,__VA_ARGS__)
139 #define RC_ARGS_PAIR_LOOP2() RC_ARGS_PAIR_LOOP
140 /// @endcond
141 
142 /// \def RC_ARGS_PAIR
143 /// Does RC_ARGS_PAIR(Odd,Even,a,b,c,d) --> Odd(a)Even(b),Odd(c)Even(d)
144 /** @see RC_ARGS_LIST
145  */
146 #define RC_ARGS_PAIR(odd,even,...) RC_EV(RC_ARGS_PAIR_FIRST(RC_EMPTY(__VA_ARGS__))(odd,even,__VA_ARGS__))
147 
148 /// \def RC_ARGS_DECLIST
149 /// Does "RC_ARGS_DECLIST(int,a,int,b)" --> "int a,int b"
150 #define RC_ARGS_DECLIST(...) RC_ARGS_PAIR(RC_NOP,RC_NOP,__VA_ARGS__)
151 /// \def RC_ARGS_PARAMLIST
152 /// Does "RC_ARGS_PARAMLIST(int,a,int,b)" --> "a,b"
153 #define RC_ARGS_PARAMLIST(...) RC_ARGS_PAIR(RC_ARGS_EAT,RC_NOP,__VA_ARGS__)
154 
155 /// @cond UNDOC
156 #define RC_DEBOUT_HELP(v) << ", " << #v << " = " << v
157 /// @endcond
158 
159 /// \def RC_DEBOUT
160 /// Use RC_DEBOUT(var1, ..., varN) for a flushed stderr debug printout of
161 /// variables.
162 /** This also prints the file name and line number, and can be used to mark
163  * when execution reaches a point with no variables as RC_DEBOUT(). The
164  * default destination stream of std::cerr can be changed by defining
165  * RC_DEBOUT_STREAM in RCconfig.h or earlier.
166  */
167 #define RC_DEBOUT(...) RC_DEBOUT_STREAM << __FILE__ << ":" << __LINE__ RC_ARGS_EACH(RC_DEBOUT_HELP,__VA_ARGS__) << std::endl;
168 
169  /// Mark an unused variable to suppress warnings.
170  template<class T> inline void UnusedVar(const T&) { }
171 /// \def RC_UNUSED_PARAM
172 /// Use in function headers as void func(int RC_UNUSED_PARAM(x)) to suppress
173 /// warnings about non-use.
174 #ifdef __GNUC__
175 #define RC_UNUSED_PARAM(v) v __attribute__((unused))
176 #elif defined(__LCLINT__)
177 #define RC_UNUSED_PARAM(v) /*@unused@*/ v
178 #else
179 #define RC_UNUSED_PARAM(v) v
180 #endif
181 
182 /// \def RC_DYNAMIC_LOAD_FUNC_RAW
183 /// Use as RC_DYNAMIC_LOAD_FUNC_RAW(FuncName,Library) to load FuncName from the
184 /// dynamic library file Library.
185 /** This creates a static function pointer named FuncName in-place to provide
186  * access to the loaded library. As it overrides FuncName, the previous
187  * declaration of FuncName MUST be in an outer scope (outside of the function
188  * where this is called). For example, include the original definition from a
189  * header, and use this inside of a function or namespace. After this macro,
190  * call FuncName with the same syntax as you would the previously declared
191  * FuncName. This macro is defined for both Linux and Windows. In the event
192  * of an error, FuncName is null. This must be checked in the current version
193  * of this macro. A safer version with exception throws is
194  * RC_DYNAMIC_LOAD_FUNC.
195  */
196 #ifdef unix
197 #define RC_DYNAMIC_LOAD_FUNC_RAW(FuncName,Library) \
198  void* FuncName##_library = dlopen(Library, RTLD_LAZY | RTLD_GLOBAL); \
199  static decltype(&FuncName) FuncName = (FuncName##_library) ? \
200  reinterpret_cast<decltype(FuncName)> \
201  (dlsym(FuncName##_library,#FuncName)): 0;
202 #elif defined(WIN32)
203 #define RC_DYNAMIC_LOAD_FUNC_RAW(FuncName,Library) \
204  HMODULE FuncName##_library = LoadLibrary(Library); \
205  static decltype(&FuncName) FuncName = (FuncName##_library) ? \
206  reinterpret_cast<decltype(FuncName)> \
207  (GetProcAddress(FuncName##_library,#FuncName)): 0;
208 #endif
209 
210 
211 /// @cond UNDOC
212 #define RC_CONSTWRAP_HELP2(Ret,Func,Line,...) \
213  inline Ret Func(RC_ARGS_DECLIST(__VA_ARGS__)) { return RC_CONSTWRAP_Helper__##Line<Ret>(RC_ARGS_PARAMLIST(,*this,__VA_ARGS__)); } \
214  /** \brief Const version of Func */ \
215  inline const Ret Func(RC_ARGS_DECLIST(__VA_ARGS__)) const { return RC_CONSTWRAP_Helper__##Line<const Ret>(RC_ARGS_PARAMLIST(,*this,__VA_ARGS__)); } \
216  template<class FHRet, class Self> \
217  /** \private */ \
218  inline static FHRet RC_CONSTWRAP_Helper__##Line(RC_ARGS_DECLIST(Self&, self, __VA_ARGS__))
219 #define RC_CONSTWRAP_HELP(Ret,Func,Line,...) RC_CONSTWRAP_HELP2(Ret,Func,Line,__VA_ARGS__)
220 /// @endcond
221 /// \def RC_CONSTWRAP
222 /// Use to metaprogrammatically generate paired const and non-const getters.
223 /** The first parameter is the return type, and the second the function name.
224  * Subsequent parameters are pairs of type and variable name for function
225  * parameters. Access member variable x with "self.x".
226  * E.g.: RC_CONSTWRAP(int&, MyFunc, size_t, index) {
227  * return self.array[index]; }
228  */
229 #define RC_CONSTWRAP(Ret,Func,...) RC_CONSTWRAP_HELP(Ret,Func,__LINE__,__VA_ARGS__)
230 
231 
232 /// \def RC_GetTc
233 /// Generates wrappers for const Get_T functions.
234 #define RC_GetTc(T) \
235  /** \brief Overloaded function to extract type T from this class.
236  @param x The reference to which the value will be assigned. */ \
237  inline void Get(T &x) const { x = Get_##T(); }
238 /// \def RC_GetT
239 /// Generates wrappers for Get_T functions.
240 #define RC_GetT(T) \
241  /** \brief Overloaded function to extract type T from this class.
242  @param x The reference to which the value will be assigned. */ \
243  inline void Get(T &x) { x = Get_##T(); }
244 
245 
246 /// \def RC_DEFAULT_COMPARISON
247 /// Given == and <, generates !=, >, <=, and >=
248 #define RC_DEFAULT_COMPARISON() \
249  /** \brief True if not equal. */ \
250  template<class AnyValidType> \
251  inline bool operator!= (const AnyValidType& other) const { \
252  return !((*this) == other); \
253  } \
254  /** \brief True if other is less than this object. */ \
255  template<class AnyValidType> \
256  inline bool operator> (const AnyValidType& other) const { \
257  return other < (*this); \
258  } \
259  /** \brief True if other is not less than this object. */ \
260  template<class AnyValidType> \
261  inline bool operator<= (const AnyValidType& other) const { \
262  return !(other < (*this)); \
263  } \
264  /** \brief True if this object is not less than other. */ \
265  template<class AnyValidType> \
266  inline bool operator>= (const AnyValidType& other) const { \
267  return !((*this) < other); \
268  }
269 
270  /// \def RC_STREAM_RAWWRAP
271  /// Provides stream output for a class via Raw.
272 #define RC_STREAM_RAWWRAP(Type) \
273  /** \brief A convenience stream output for displaying the enclosed \
274  object. */ \
275  template <class T> \
276  inline std::ostream& operator<< (std::ostream &out, Type<T> obj) { \
277  return (out << obj.Raw()); \
278  }
279 
280  /// \def RC_DefaultCopyMove
281  /// Provides explicit default copy and move constructors and assignment.
282 #ifdef CPP11
283  #define RC_DefaultCopyMove(ClassName) \
284  /** \brief Default copy constructor. */ \
285  ClassName(const ClassName&) = default; \
286  /** \brief Default move constructor. */ \
287  ClassName(ClassName&&) = default; \
288  /** \brief Default copy assignment operator. */ \
289  ClassName& operator=(const ClassName&) & = default; \
290  /** \brief Default move assignment operator. */ \
291  ClassName& operator=(ClassName&&) & = default;
292 #else
293  #define RC_DefaultCopyMove(ClassName)
294 #endif
295 
296 /// \def RC_ForIndex(i, cont)
297 /// Creates i of type equivalent to cont.size(), and loops over [0,cont.size).
298 /// Use like: RC_ForIndex(i, cont) { cout << cont[i]; }
299 #define RC_ForIndex(i, cont) for (decltype(cont.size()) i = 0; i < cont.size(); ++i)
300 
301 /// \def RC_ForEach(e, cont)
302 /// Provides element auto&& e derived from the cont operator[], and loops over
303 /// [0,cont.size). Like a range-based for loop, but using operator[].
304 /// Use like: RC_ForEach(e, cont) { cout << e; }
305 #define RC_ForEach(e, cont) for(decltype(cont.size()) RC_ForEach_i=0; RC_ForEach_i<cont.size(); ++RC_ForEach_i)if(bool RC_ForEach_b=false);else for(auto&& e=cont[RC_ForEach_i];RC_ForEach_b^=1;)
306 
307 /// \def RC_ForRange(i, start, past_end)
308 /// Creates a for loop over i with type deduction from the past_end.
309 #define RC_ForRange(i, start, past_end) for (decltype(past_end) i = start; i < past_end; ++i)
310 
311 /// \def RC_Repeat(times)
312 /// Repeats the following block the specified times, with automatic type
313 /// deduction.
314 #define RC_Repeat(times) for (decltype(times) RC_Repeat_i = 0; RC_Repeat_i < times; ++RC_Repeat_i)
315 
316 }
317 
318 #endif // MY_MACROS_H
319 
The version information and configuration settings for RC Lib.
Definition: APtr.h:25
void UnusedVar(const T &)
Mark an unused variable to suppress warnings.
Definition: Macros.h:170
email address
— (c) 2015