Thrill  0.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
core.hpp
Go to the documentation of this file.
1 /*******************************************************************************
2  * tlx/die/core.hpp
3  *
4  * Part of tlx - http://panthema.net/tlx
5  *
6  * Copyright (C) 2016-2018 Timo Bingmann <[email protected]>
7  *
8  * All rights reserved. Published under the Boost Software License, Version 1.0
9  ******************************************************************************/
10 
11 #ifndef TLX_DIE_CORE_HEADER
12 #define TLX_DIE_CORE_HEADER
13 
14 #include <cstring>
15 #include <sstream>
16 #include <stdexcept>
17 #include <string>
18 
19 namespace tlx {
20 
21 /******************************************************************************/
22 // die macros
23 
24 //! die with message - either throw an exception or die via std::terminate()
25 void die_with_message(const std::string& msg);
26 
27 //! die with message - either throw an exception or die via std::terminate()
28 void die_with_message(const char* msg, const char* file, size_t line);
29 
30 //! die with message - either throw an exception or die via std::terminate()
31 void die_with_message(const std::string& msg, const char* file, size_t line);
32 
33 //! Instead of std::terminate(), throw the output the message via an exception.
34 #define tlx_die_with_sstream(msg) \
35  do { \
36  std::ostringstream oss__; \
37  oss__ << msg << " @ " << __FILE__ << ':' << __LINE__; \
38  ::tlx::die_with_message(oss__.str()); \
39  std::terminate(); /* tell compiler this never returns */ \
40  } while (false)
41 
42 //! Instead of std::terminate(), throw the output the message via an exception.
43 #define tlx_die(msg) \
44  do { \
45  tlx_die_with_sstream("DIE: " << msg); \
46  } while (false)
47 
48 //! Exception thrown by die_with_message() if
49 class DieException : public std::runtime_error
50 {
51 public:
52  explicit DieException(const std::string& message);
53 };
54 
55 //! Switch between dying via std::terminate() and throwing an exception.
56 //! Alternatively define the macro TLX_DIE_WITH_EXCEPTION=1
57 bool set_die_with_exception(bool b);
58 
59 /******************************************************************************/
60 // die_unless() and die_if()
61 
62 //! Check condition X and die miserably if false. Same as assert() except this
63 //! is also active in Release mode.
64 #define tlx_die_unless(X) \
65  do { \
66  if (!(X)) { \
67  ::tlx::die_with_message( \
68  "DIE: Assertion \"" #X "\" failed!", __FILE__, __LINE__); \
69  } \
70  } while (false)
71 
72 //! Check condition X and die miserably if true. Opposite of assert() except
73 //! this is also active in Release mode.
74 #define tlx_die_if(X) \
75  do { \
76  if (X) { \
77  ::tlx::die_with_message( \
78  "DIE: Assertion \"" #X "\" succeeded!", __FILE__, __LINE__); \
79  } \
80  } while (false)
81 
82 //! Check condition X and die miserably if false. Same as tlx_die_unless()
83 //! except the user additionally passes a message.
84 #define tlx_die_verbose_unless(X, msg) \
85  do { \
86  if (!(X)) { \
87  tlx_die_with_sstream( \
88  "DIE: Assertion \"" #X "\" failed!\n" << msg << '\n'); \
89  } \
90  } while (false)
91 
92 //! Check condition X and die miserably if false. Same as tlx_die_if()
93 //! except the user additionally passes a message.
94 #define tlx_die_verbose_if(X, msg) \
95  do { \
96  if ((X)) { \
97  tlx_die_with_sstream( \
98  "DIE: Assertion \"" #X "\" succeeded!\n" << msg << '\n'); \
99  } \
100  } while (false)
101 
102 /******************************************************************************/
103 // die_unequal()
104 
105 //! helper method to compare two values in die_unequal()
106 template <typename TypeA, typename TypeB>
107 inline bool die_equal_compare(TypeA a, TypeB b) {
108  return a == b;
109 }
110 
111 template <>
112 inline bool die_equal_compare(const char* a, const char* b) {
113  // compare string contents
114  return std::strcmp(a, b) == 0;
115 }
116 
117 template <>
118 inline bool die_equal_compare(float a, float b) {
119  // special case for NAN
120  return a != a ? b != b : a == b;
121 }
122 
123 template <>
124 inline bool die_equal_compare(double a, double b) {
125  // special case for NAN
126  return a != a ? b != b : a == b;
127 }
128 
129 //! Check that X == Y or die miserably, but output the values of X and Y for
130 //! better debugging.
131 #define tlx_die_unequal(X, Y) \
132  do { \
133  auto x__ = (X); /* NOLINT */ \
134  auto y__ = (Y); /* NOLINT */ \
135  if (!::tlx::die_equal_compare(x__, y__)) \
136  tlx_die_with_sstream("DIE-UNEQUAL: " #X " != " #Y " : " \
137  "\"" << x__ << "\" != \"" << y__ << "\""); \
138  } while (false)
139 
140 //! Check that X == Y or die miserably, but output the values of X and Y for
141 //! better debugging. Only active if NDEBUG is not defined.
142 #ifdef NDEBUG
143 #define tlx_assert_equal(X, Y)
144 #else
145 #define tlx_assert_equal(X, Y) die_unequal(X, Y)
146 #endif
147 
148 //! Check that X == Y or die miserably, but output the values of X and Y for
149 //! better debugging. Same as tlx_die_unequal() except the user additionally
150 //! pass a message.
151 #define tlx_die_verbose_unequal(X, Y, msg) \
152  do { \
153  auto x__ = (X); /* NOLINT */ \
154  auto y__ = (Y); /* NOLINT */ \
155  if (!::tlx::die_equal_compare(x__, y__)) \
156  tlx_die_with_sstream("DIE-UNEQUAL: " #X " != " #Y " : " \
157  "\"" << x__ << "\" != \"" << y__ << "\"\n" << \
158  msg << '\n'); \
159  } while (false)
160 
161 /******************************************************************************/
162 // die_unequal_eps()
163 
164 //! simple replacement for std::abs
165 template <typename Type>
166 inline Type die_unequal_eps_abs(const Type& t) {
167  return t < 0 ? -t : t;
168 }
169 
170 //! helper method to compare two values in die_unequal_eps()
171 template <typename TypeA, typename TypeB>
172 inline bool die_equal_eps_compare(TypeA x, TypeB y, double eps) {
173  // special case for NAN
174  return x != x ? y != y : die_unequal_eps_abs(x - y) <= eps;
175 }
176 
177 //! Check that ABS(X - Y) <= eps or die miserably, but output the values of X
178 //! and Y for better debugging.
179 #define tlx_die_unequal_eps(X, Y, eps) \
180  do { \
181  auto x__ = (X); /* NOLINT */ \
182  auto y__ = (Y); /* NOLINT */ \
183  if (!::tlx::die_equal_eps_compare(x__, y__, eps)) \
184  tlx_die("DIE-UNEQUAL-EPS: " #X " != " #Y " : " \
185  << std::setprecision(18) \
186  << "\"" << x__ << "\" != \"" << y__ << "\""); \
187  } while (false)
188 
189 //! Check that ABS(X - Y) <= eps or die miserably, but output the values of X
190 //! and Y for better debugging. Same as tlx_die_unequal_eps() except the user
191 //! additionally passes a message.
192 #define tlx_die_verbose_unequal_eps(X, Y, eps, msg) \
193  do { \
194  auto x__ = (X); /* NOLINT */ \
195  auto y__ = (Y); /* NOLINT */ \
196  if (!::tlx::die_equal_eps_compare(x__, y__, eps)) \
197  tlx_die("DIE-UNEQUAL-EPS: " #X " != " #Y " : " \
198  << std::setprecision(18) \
199  << "\"" << x__ << "\" != \"" << y__ << "\"\n" << \
200  msg << '\n'); \
201  } while (false)
202 
203 //! Check that ABS(X - Y) <= 0.000001 or die miserably, but output the values of
204 //! X and Y for better debugging.
205 #define tlx_die_unequal_eps6(X, Y) \
206  die_unequal_eps(X, Y, 1e-6)
207 
208 //! Check that ABS(X - Y) <= 0.000001 or die miserably, but output the values of
209 //! X and Y for better debugging. Same as tlx_die_unequal_eps6() except the user
210 //! additionally passes a message.
211 #define tlx_die_verbose_unequal_eps6(X, Y, msg) \
212  die_verbose_unequal_eps(X, Y, 1e-6, msg)
213 
214 /******************************************************************************/
215 // die_equal()
216 
217 //! Die miserably if X == Y, but first output the values of X and Y for better
218 //! debugging.
219 #define tlx_die_equal(X, Y) \
220  do { \
221  auto x__ = (X); /* NOLINT */ \
222  auto y__ = (Y); /* NOLINT */ \
223  if (::tlx::die_equal_compare(x__, y__)) \
224  tlx_die_with_sstream("DIE-EQUAL: " #X " == " #Y " : " \
225  "\"" << x__ << "\" == \"" << y__ << "\""); \
226  } while (false)
227 
228 //! Die miserably if X == Y, but first output the values of X and Y for better
229 //! debugging. Only active if NDEBUG is not defined.
230 #ifdef NDEBUG
231 #define tlx_assert_unequal(X, Y)
232 #else
233 #define tlx_assert_unequal(X, Y) die_equal(X, Y)
234 #endif
235 
236 //! Die miserably if X == Y, but first output the values of X and Y for better
237 //! debugging. Same as tlx_die_equal() except the user additionally passes a
238 //! message.
239 #define tlx_die_verbose_equal(X, Y, msg) \
240  do { \
241  auto x__ = (X); /* NOLINT */ \
242  auto y__ = (Y); /* NOLINT */ \
243  if (::tlx::die_equal_compare(x__, y__)) \
244  tlx_die_with_sstream("DIE-EQUAL: " #X " == " #Y " : " \
245  "\"" << x__ << "\" == \"" << y__ << "\"\n" << \
246  msg << '\n'); \
247  } while (false)
248 
249 /******************************************************************************/
250 // die_unless_throws()
251 
252 //! Define to check that [code] throws and exception of given type
253 #define tlx_die_unless_throws(code, exception_type) \
254  do { \
255  try { \
256  code; \
257  } \
258  catch (const exception_type&) { \
259  break; \
260  } \
261  ::tlx::die_with_message( \
262  "DIE-UNLESS-THROWS: " #code " - NO EXCEPTION " #exception_type, \
263  __FILE__, __LINE__); \
264  } while (false)
265 
266 } // namespace tlx
267 
268 #endif // !TLX_DIE_CORE_HEADER
269 
270 /******************************************************************************/
Type die_unequal_eps_abs(const Type &t)
simple replacement for std::abs
Definition: core.hpp:166
bool set_die_with_exception(bool b)
Definition: core.cpp:52
bool die_equal_compare(TypeA a, TypeB b)
helper method to compare two values in die_unequal()
Definition: core.hpp:107
Type
VFS object type.
Definition: file_io.hpp:52
DieException(const std::string &message)
Definition: core.cpp:49
bool die_equal_eps_compare(TypeA x, TypeB y, double eps)
helper method to compare two values in die_unequal_eps()
Definition: core.hpp:172
void die_with_message(const std::string &msg)
die with message - either throw an exception or die via std::terminate()
Definition: core.cpp:29
Exception thrown by die_with_message() if.
Definition: core.hpp:49
list x
Definition: gen_data.py:39
std::basic_string< char, std::char_traits< char >, Allocator< char > > string
string with Manager tracking
Definition: allocator.hpp:220