ZeroErr
config.h
Go to the documentation of this file.
1 #pragma once
2 
3 #define ZEROERR_VERSION_MAJOR 0
4 #define ZEROERR_VERSION_MINOR 3
5 #define ZEROERR_VERSION_PATCH 0
6 #define ZEROERR_VERSION \
7  (ZEROERR_VERSION_MAJOR * 10000 + ZEROERR_VERSION_MINOR * 100 + ZEROERR_VERSION_PATCH)
8 
9 #define ZEROERR_STR(x) #x
10 
11 #define ZEROERR_VERSION_STR_BUILDER(a, b, c) ZEROERR_STR(a) "." ZEROERR_STR(b) "." ZEROERR_STR(c)
12 #define ZEROERR_VERSION_STR \
13  ZEROERR_VERSION_STR_BUILDER(ZEROERR_VERSION_MAJOR, ZEROERR_VERSION_MINOR, ZEROERR_VERSION_PATCH)
14 
15 // If you just wish to use the color without dynamic
16 // enable or disable it, you can uncomment the following line
17 // #define ZEROERR_ALWAYS_COLORFUL
18 // #define ZEROERR_DISABLE_COLORFUL
19 
20 // If you wish to use the whole library without thread safety, uncomment the following line
21 // #define ZEROERR_NO_THREAD_SAFE
22 
23 // If you wish to disable auto initialization of the system
24 // #define ZEROERR_DISABLE_AUTO_INIT
25 
26 // If you didn't wish override operator<< for ostream, we can disable it
27 // #define ZEROERR_DISABLE_OSTREAM_OVERRIDE
28 
29 // If you wish to disable AND, OR macro
30 // #define ZEROERR_DISABLE_COMPLEX_AND_OR
31 
32 // If you wish ot disable BDD style macros
33 // #define ZEROERR_DISABLE_BDD
34 
35 // Detect C++ standard with a cross-platform way
36 
37 #ifdef _MSC_VER
38 #define ZEROERR_CPLUSPLUS _MSVC_LANG
39 #else
40 #define ZEROERR_CPLUSPLUS __cplusplus
41 #endif
42 
43 #if ZEROERR_CPLUSPLUS >= 202300L
44 #define ZEROERR_CXX_STANDARD 23
45 #elif ZEROERR_CPLUSPLUS >= 202002L
46 #define ZEROERR_CXX_STANDARD 20
47 #elif ZEROERR_CPLUSPLUS >= 201703L
48 #define ZEROERR_CXX_STANDARD 17
49 #elif ZEROERR_CPLUSPLUS >= 201402L
50 #define ZEROERR_CXX_STANDARD 14
51 #elif ZEROERR_CPLUSPLUS >= 201103L
52 #define ZEROERR_CXX_STANDARD 11
53 #else
54 #error "Unsupported C++ standard detected. ZeroErr requires C++11 or later."
55 #endif
56 
57 #if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__))
58 #define ZEROERR_OS_UNIX
59 #if defined(__linux__)
60 #define ZEROERR_OS_LINUX
61 #endif
62 #elif defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
63 #define ZEROERR_OS_WINDOWS
64 #else
65 #define ZEROERR_OS_UNKNOWN
66 #endif
67 
68 
69 #if defined(NDEBUG) && !defined(ZEROERR_ALWAYS_ASSERT)
70 // FIXME: we should safely remove the assert in IF statement
71 // #define ZEROERR_NO_ASSERT
72 #endif
73 
74 // This is used for generating a unique name based on the file name and line number
75 #define ZEROERR_CAT_IMPL(s1, s2) s1##s2
76 #define ZEROERR_CAT(x, s) ZEROERR_CAT_IMPL(x, s)
77 
78 // The following macros are used to check the arguments is empty or not
79 // from: https://gustedt.wordpress.com/2010/06/08/detect-empty-macro-arguments/
80 #define ZEROERR_ARG16(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, ...) _15
81 #define ZEROERR_HAS_COMMA(...) \
82  ZEROERR_ARG16(__VA_ARGS__, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0)
83 #define ZEROERR_TRIGGER_PARENTHESIS_(...) ,
84 
85 #define ZEROERR_ISEMPTY(...) \
86  _ZEROERR_ISEMPTY(/* test if there is just one argument, eventually an empty \
87  one */ \
88  ZEROERR_HAS_COMMA(__VA_ARGS__), /* test if ZEROERR_TRIGGER_PARENTHESIS_ \
89  together with the argument adds a comma */ \
90  ZEROERR_HAS_COMMA(ZEROERR_TRIGGER_PARENTHESIS_ \
91  __VA_ARGS__), /* test if the argument together with \
92  a parenthesis adds a comma */ \
93  ZEROERR_HAS_COMMA(__VA_ARGS__( \
94  /*empty*/)), /* test if placing it between ZEROERR_TRIGGER_PARENTHESIS_ \
95  and the parenthesis adds a comma */ \
96  ZEROERR_HAS_COMMA(ZEROERR_TRIGGER_PARENTHESIS_ __VA_ARGS__(/*empty*/)))
97 
98 #define ZEROERR_PASTE5(_0, _1, _2, _3, _4) _0##_1##_2##_3##_4
99 #define _ZEROERR_ISEMPTY(_0, _1, _2, _3) \
100  ZEROERR_HAS_COMMA(ZEROERR_PASTE5(_IS_EMPTY_CASE_, _0, _1, _2, _3))
101 #define _IS_EMPTY_CASE_0001 ,
102 
103 
104 // The counter is used to generate a unique name
105 #ifdef __COUNTER__
106 #define ZEROERR_NAMEGEN(x) ZEROERR_CAT(x, __COUNTER__)
107 #else // __COUNTER__
108 #define ZEROERR_NAMEGEN(x) ZEROERR_CAT(x, __LINE__)
109 #endif // __COUNTER__
110 
111 #ifdef ZEROERR_OS_LINUX
112 #define ZEROERR_PERF
113 #endif
114 
115 #ifdef ZEROERR_DISABLE_ASSERTS_RETURN_VALUES
116 #define ZEROERR_FUNC_SCOPE_BEGIN do
117 #define ZEROERR_FUNC_SCOPE_END while (0)
118 #define ZEROERR_FUNC_SCOPE_RET(v) (void)0
119 #else
120 #define ZEROERR_FUNC_SCOPE_BEGIN [&]
121 #define ZEROERR_FUNC_SCOPE_END ()
122 #define ZEROERR_FUNC_SCOPE_RET(v) return v
123 #endif
124 
125 #ifndef ZEROERR_NO_SHORT_LOG_MACRO
126 #define ZEROERR_USE_SHORT_LOG_MACRO
127 #endif
128 
129 #define ZEROERR_EXPAND(x) x
130 
131 
132 // =================================================================================================
133 // == COMPILER Detector ============================================================================
134 // =================================================================================================
135 
136 #define ZEROERR_COMPILER(MAJOR, MINOR, PATCH) ((MAJOR) * 10000000 + (MINOR) * 100000 + (PATCH))
137 
138 // GCC/Clang and GCC/MSVC are mutually exclusive, but Clang/MSVC are not because of clang-cl...
139 #if defined(_MSC_VER) && defined(_MSC_FULL_VER)
140 #if _MSC_VER == _MSC_FULL_VER / 10000
141 #define ZEROERR_MSVC ZEROERR_COMPILER(_MSC_VER / 100, _MSC_VER % 100, _MSC_FULL_VER % 10000)
142 #else // MSVC
143 #define ZEROERR_MSVC \
144  ZEROERR_COMPILER(_MSC_VER / 100, (_MSC_FULL_VER / 100000) % 100, _MSC_FULL_VER % 100000)
145 #endif // MSVC
146 #endif // MSVC
147 #if defined(__clang__) && defined(__clang_minor__) && defined(__clang_patchlevel__)
148 #define ZEROERR_CLANG ZEROERR_COMPILER(__clang_major__, __clang_minor__, __clang_patchlevel__)
149 #elif defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__GNUC_PATCHLEVEL__) && \
150  !defined(__INTEL_COMPILER)
151 #define ZEROERR_GCC ZEROERR_COMPILER(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__)
152 #endif // GCC
153 #if defined(__INTEL_COMPILER)
154 #define ZEROERR_ICC ZEROERR_COMPILER(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, 0)
155 #endif // ICC
156 
157 #ifndef ZEROERR_MSVC
158 #define ZEROERR_MSVC 0
159 #endif // ZEROERR_MSVC
160 #ifndef ZEROERR_CLANG
161 #define ZEROERR_CLANG 0
162 #endif // ZEROERR_CLANG
163 #ifndef ZEROERR_GCC
164 #define ZEROERR_GCC 0
165 #endif // ZEROERR_GCC
166 #ifndef ZEROERR_ICC
167 #define ZEROERR_ICC 0
168 #endif // ZEROERR_ICC
169 
170 
171 // =================================================================================================
172 // == COMPILER WARNINGS HELPERS ====================================================================
173 // =================================================================================================
174 
175 #if ZEROERR_CLANG && !ZEROERR_ICC
176 #define ZEROERR_PRAGMA_TO_STR(x) _Pragma(#x)
177 #define ZEROERR_CLANG_SUPPRESS_WARNING_PUSH _Pragma("clang diagnostic push")
178 #define ZEROERR_CLANG_SUPPRESS_WARNING(w) ZEROERR_PRAGMA_TO_STR(clang diagnostic ignored w)
179 #define ZEROERR_CLANG_SUPPRESS_WARNING_POP _Pragma("clang diagnostic pop")
180 #define ZEROERR_CLANG_SUPPRESS_WARNING_WITH_PUSH(w) \
181  ZEROERR_CLANG_SUPPRESS_WARNING_PUSH ZEROERR_CLANG_SUPPRESS_WARNING(w)
182 #else // ZEROERR_CLANG
183 #define ZEROERR_CLANG_SUPPRESS_WARNING_PUSH
184 #define ZEROERR_CLANG_SUPPRESS_WARNING(w)
185 #define ZEROERR_CLANG_SUPPRESS_WARNING_POP
186 #define ZEROERR_CLANG_SUPPRESS_WARNING_WITH_PUSH(w)
187 #endif // ZEROERR_CLANG
188 
189 #if ZEROERR_GCC
190 #define ZEROERR_PRAGMA_TO_STR(x) _Pragma(#x)
191 #define ZEROERR_GCC_SUPPRESS_WARNING_PUSH _Pragma("GCC diagnostic push")
192 #define ZEROERR_GCC_SUPPRESS_WARNING(w) ZEROERR_PRAGMA_TO_STR(GCC diagnostic ignored w)
193 #define ZEROERR_GCC_SUPPRESS_WARNING_POP _Pragma("GCC diagnostic pop")
194 #define ZEROERR_GCC_SUPPRESS_WARNING_WITH_PUSH(w) \
195  ZEROERR_GCC_SUPPRESS_WARNING_PUSH ZEROERR_GCC_SUPPRESS_WARNING(w)
196 #else // ZEROERR_GCC
197 #define ZEROERR_GCC_SUPPRESS_WARNING_PUSH
198 #define ZEROERR_GCC_SUPPRESS_WARNING(w)
199 #define ZEROERR_GCC_SUPPRESS_WARNING_POP
200 #define ZEROERR_GCC_SUPPRESS_WARNING_WITH_PUSH(w)
201 #endif // ZEROERR_GCC
202 
203 #if ZEROERR_MSVC
204 #define ZEROERR_MSVC_SUPPRESS_WARNING_PUSH __pragma(warning(push))
205 #define ZEROERR_MSVC_SUPPRESS_WARNING(w) __pragma(warning(disable : w))
206 #define ZEROERR_MSVC_SUPPRESS_WARNING_POP __pragma(warning(pop))
207 #define ZEROERR_MSVC_SUPPRESS_WARNING_WITH_PUSH(w) \
208  ZEROERR_MSVC_SUPPRESS_WARNING_PUSH ZEROERR_MSVC_SUPPRESS_WARNING(w)
209 #else // ZEROERR_MSVC
210 #define ZEROERR_MSVC_SUPPRESS_WARNING_PUSH
211 #define ZEROERR_MSVC_SUPPRESS_WARNING(w)
212 #define ZEROERR_MSVC_SUPPRESS_WARNING_POP
213 #define ZEROERR_MSVC_SUPPRESS_WARNING_WITH_PUSH(w)
214 #endif // ZEROERR_MSVC
215 
216 // =================================================================================================
217 // == COMPILER WARNINGS ============================================================================
218 // =================================================================================================
219 
220 // both the header and the implementation suppress all of these,
221 // so it only makes sense to aggregate them like so
222 #define ZEROERR_SUPPRESS_COMMON_WARNINGS_PUSH \
223  ZEROERR_CLANG_SUPPRESS_WARNING_PUSH \
224  ZEROERR_CLANG_SUPPRESS_WARNING("-Wunknown-pragmas") \
225  ZEROERR_CLANG_SUPPRESS_WARNING("-Wweak-vtables") \
226  ZEROERR_CLANG_SUPPRESS_WARNING("-Wpadded") \
227  ZEROERR_CLANG_SUPPRESS_WARNING("-Wmissing-prototypes") \
228  ZEROERR_CLANG_SUPPRESS_WARNING("-Wc++98-compat") \
229  ZEROERR_CLANG_SUPPRESS_WARNING("-Wc++98-compat-pedantic") \
230  \
231  ZEROERR_GCC_SUPPRESS_WARNING_PUSH \
232  ZEROERR_GCC_SUPPRESS_WARNING("-Wunknown-pragmas") \
233  ZEROERR_GCC_SUPPRESS_WARNING("-Wpragmas") \
234  ZEROERR_GCC_SUPPRESS_WARNING("-Weffc++") \
235  ZEROERR_GCC_SUPPRESS_WARNING("-Wstrict-overflow") \
236  ZEROERR_GCC_SUPPRESS_WARNING("-Wstrict-aliasing") \
237  ZEROERR_GCC_SUPPRESS_WARNING("-Wmissing-declarations") \
238  ZEROERR_GCC_SUPPRESS_WARNING("-Wuseless-cast") \
239  ZEROERR_GCC_SUPPRESS_WARNING("-Wnoexcept") \
240  \
241  ZEROERR_MSVC_SUPPRESS_WARNING_PUSH \
242  /* these 4 also disabled globally via cmake: */ \
243  ZEROERR_MSVC_SUPPRESS_WARNING(4514) /* unreferenced inline function has been removed */ \
244  ZEROERR_MSVC_SUPPRESS_WARNING(4571) /* SEH related */ \
245  ZEROERR_MSVC_SUPPRESS_WARNING(4710) /* function not inlined */ \
246  ZEROERR_MSVC_SUPPRESS_WARNING(4711) /* function selected for inline expansion*/ \
247  /* common ones */ \
248  ZEROERR_MSVC_SUPPRESS_WARNING(4616) /* invalid compiler warning */ \
249  ZEROERR_MSVC_SUPPRESS_WARNING(4619) /* invalid compiler warning */ \
250  ZEROERR_MSVC_SUPPRESS_WARNING(4996) /* The compiler encountered a deprecated declaration */ \
251  ZEROERR_MSVC_SUPPRESS_WARNING(4706) /* assignment within conditional expression */ \
252  ZEROERR_MSVC_SUPPRESS_WARNING(4512) /* 'class' : assignment operator could not be generated */ \
253  ZEROERR_MSVC_SUPPRESS_WARNING(4127) /* conditional expression is constant */ \
254  ZEROERR_MSVC_SUPPRESS_WARNING(4820) /* padding */ \
255  ZEROERR_MSVC_SUPPRESS_WARNING(4625) /* copy constructor was implicitly deleted */ \
256  ZEROERR_MSVC_SUPPRESS_WARNING(4626) /* assignment operator was implicitly deleted */ \
257  ZEROERR_MSVC_SUPPRESS_WARNING(5027) /* move assignment operator implicitly deleted */ \
258  ZEROERR_MSVC_SUPPRESS_WARNING(5026) /* move constructor was implicitly deleted */ \
259  ZEROERR_MSVC_SUPPRESS_WARNING(4640) /* construction of local static object not thread-safe */ \
260  ZEROERR_MSVC_SUPPRESS_WARNING(5045) /* Spectre mitigation for memory load */ \
261  ZEROERR_MSVC_SUPPRESS_WARNING(5264) /* 'variable-name': 'const' variable is not used */ \
262  /* static analysis */ \
263  ZEROERR_MSVC_SUPPRESS_WARNING(26439) /* Function may not throw. Declare it 'noexcept' */ \
264  ZEROERR_MSVC_SUPPRESS_WARNING(26495) /* Always initialize a member variable */ \
265  ZEROERR_MSVC_SUPPRESS_WARNING(26451) /* Arithmetic overflow ... */ \
266  ZEROERR_MSVC_SUPPRESS_WARNING(26444) /* Avoid unnamed objects with custom ctor and dtor... */ \
267  ZEROERR_MSVC_SUPPRESS_WARNING(26812) /* Prefer 'enum class' over 'enum' */
268 
269 #define ZEROERR_SUPPRESS_COMMON_WARNINGS_POP \
270  ZEROERR_CLANG_SUPPRESS_WARNING_POP \
271  ZEROERR_GCC_SUPPRESS_WARNING_POP \
272  ZEROERR_MSVC_SUPPRESS_WARNING_POP
273 
274 
275 #define ZEROERR_MAKE_STD_HEADERS_CLEAN_FROM_WARNINGS_ON_WALL_BEGIN \
276  ZEROERR_MSVC_SUPPRESS_WARNING_PUSH \
277  ZEROERR_MSVC_SUPPRESS_WARNING(4548) /* before comma no effect; expected side - effect */ \
278  ZEROERR_MSVC_SUPPRESS_WARNING(4265) /* virtual functions, but destructor is not virtual */ \
279  ZEROERR_MSVC_SUPPRESS_WARNING(4986) /* exception specification does not match previous */ \
280  ZEROERR_MSVC_SUPPRESS_WARNING(4350) /* 'member1' called instead of 'member2' */ \
281  ZEROERR_MSVC_SUPPRESS_WARNING(4668) /* not defined as a preprocessor macro */ \
282  ZEROERR_MSVC_SUPPRESS_WARNING(4365) /* signed/unsigned mismatch */ \
283  ZEROERR_MSVC_SUPPRESS_WARNING(4774) /* format string not a string literal */ \
284  ZEROERR_MSVC_SUPPRESS_WARNING(4820) /* padding */ \
285  ZEROERR_MSVC_SUPPRESS_WARNING(4625) /* copy constructor was implicitly deleted */ \
286  ZEROERR_MSVC_SUPPRESS_WARNING(4626) /* assignment operator was implicitly deleted */ \
287  ZEROERR_MSVC_SUPPRESS_WARNING(5027) /* move assignment operator implicitly deleted */ \
288  ZEROERR_MSVC_SUPPRESS_WARNING(5026) /* move constructor was implicitly deleted */ \
289  ZEROERR_MSVC_SUPPRESS_WARNING(4623) /* default constructor was implicitly deleted */ \
290  ZEROERR_MSVC_SUPPRESS_WARNING(5039) /* pointer to pot. throwing function passed to extern C */ \
291  ZEROERR_MSVC_SUPPRESS_WARNING(5045) /* Spectre mitigation for memory load */ \
292  ZEROERR_MSVC_SUPPRESS_WARNING(5105) /* macro producing 'defined' has undefined behavior */ \
293  ZEROERR_MSVC_SUPPRESS_WARNING(4738) /* storing float result in memory, loss of performance */ \
294  ZEROERR_MSVC_SUPPRESS_WARNING(5262) /* implicit fall-through */
295 
296 #define ZEROERR_MAKE_STD_HEADERS_CLEAN_FROM_WARNINGS_ON_WALL_END ZEROERR_MSVC_SUPPRESS_WARNING_POP
297 
298 #define ZEROERR_SUPPRESS_VARIADIC_MACRO \
299  ZEROERR_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wgnu-zero-variadic-macro-arguments")
300 
301 #define ZEROERR_SUPPRESS_VARIADIC_MACRO_POP ZEROERR_CLANG_SUPPRESS_WARNING_POP
302 
303 #define ZEROERR_SUPPRESS_COMPARE \
304  ZEROERR_CLANG_SUPPRESS_WARNING_PUSH \
305  ZEROERR_CLANG_SUPPRESS_WARNING("-Wsign-conversion") \
306  ZEROERR_CLANG_SUPPRESS_WARNING("-Wsign-compare") \
307  ZEROERR_CLANG_SUPPRESS_WARNING("-Wgnu-zero-variadic-macro-arguments") \
308  ZEROERR_GCC_SUPPRESS_WARNING_PUSH \
309  ZEROERR_GCC_SUPPRESS_WARNING("-Wsign-conversion") \
310  ZEROERR_GCC_SUPPRESS_WARNING("-Wsign-compare") \
311  ZEROERR_MSVC_SUPPRESS_WARNING_PUSH \
312  ZEROERR_MSVC_SUPPRESS_WARNING(4388) \
313  ZEROERR_MSVC_SUPPRESS_WARNING(4389) \
314  ZEROERR_MSVC_SUPPRESS_WARNING(4018)
315 
316 #define ZEROERR_SUPPRESS_COMPARE_POP \
317  ZEROERR_CLANG_SUPPRESS_WARNING_POP ZEROERR_GCC_SUPPRESS_WARNING_POP \
318  ZEROERR_MSVC_SUPPRESS_WARNING_POP
319 
320 #if ZEROERR_CLANG || ZEROERR_GCC
321 #define ZEROERR_UNUSED(x) x __attribute__((unused))
322 #elif defined(__LCLINT__)
323 #define ZEROERR_UNUSED(x) /*@unused@*/ x
324 #elif ZEROERR_MSVC
325 #define ZEROERR_UNUSED(x) \
326  ZEROERR_MSVC_SUPPRESS_WARNING_WITH_PUSH(4100) x ZEROERR_MSVC_SUPPRESS_WARNING_POP
327 #else
328 #define ZEROERR_UNUSED(x) x
329 #endif