siplasplas
A library for C++ reflection and introspection
assert.hpp
1 #ifndef SIPLASPLAS_UTILITY_ASSERT_HPP
2 #define SIPLASPLAS_UTILITY_ASSERT_HPP
3 
4 #include <stdexcept>
5 #include <functional>
6 #include "preprocessor.hpp"
7 #include "exception.hpp"
8 #include <siplasplas/utility/export.hpp>
9 
10 namespace cpp
11 {
12 
26 class SIPLASPLAS_UTILITY_EXPORT AssertException : public std::logic_error
27 {
28 public:
29  using std::logic_error::logic_error;
30 };
31 
43 class SIPLASPLAS_UTILITY_EXPORT AssertExpression
44 {
45 public:
55  AssertExpression(bool expressionResult,
56  const std::string& message,
57  const std::string& file,
58  std::size_t line);
59 
69  ~AssertExpression() noexcept(false);
70 
102  AssertExpression& onFailure(const std::function<void()>& callback);
103 
114  template<typename String, typename... Args>
115  AssertExpression& detail(String&& messageBody, Args&&... messageArgs)
116  {
117  _detail = ::fmt::format(std::forward<String>(messageBody), std::forward<Args>(messageArgs)...);
118  return *this;
119  }
120 
124  template<typename String, typename... Args>
125  AssertExpression& operator()(String&& messageBody, Args&&... args)
126  {
127  return detail(std::forward<String>(messageBody), std::forward<Args>(args)...);
128  }
129 
137  AssertExpression& noThrow();
138 
139 private:
140  std::string _message;
141  std::string _detail;
142  std::string _file;
143  std::size_t _line;
144  std::function<void()> _onFailureCallback;
145  bool _assertionFailed, _noThrow;
146 };
147 
155 class SIPLASPLAS_UTILITY_EXPORT DummyAssertExpression
156 {
157 public:
167  template<typename Function>
169  {
170  return *this;
171  }
172 
182  template<typename String, typename... Args>
183  DummyAssertExpression& detail(String&&, Args&&...)
184  {
185  return *this;
186  }
187 
191  template<typename String, typename... Args>
192  DummyAssertExpression& operator()(String&&, Args&&...)
193  {
194  return *this;
195  }
196 
197  /*
198  * \brief Does nothing.
199  */
200  DummyAssertExpression& noThrow()
201  {
202  return *this;
203  }
204 };
205 
206 }
207 
208 #if !defined(NDEBUG) || defined(SIPLASPLAS_ENABLE_ASSERTS)
209 #define SIPLASPLAS_ASSERTS_ENABLED
210 #define SIPLASPLAS_ASSERT_IMPL(MESSAGE, ...) ::cpp::AssertExpression((__VA_ARGS__), MESSAGE, __FILE__, __LINE__)
211 #else
212 #define SIPLASPLAS_ASSERT_IMPL(MESSAGE, ...) ::cpp::DummyAssertExpression()
213 #endif
214 
229 #define SIPLASPLAS_ASSERT(...) SIPLASPLAS_ASSERT_IMPL(SIPLASPLAS_PP_STR((__VA_ARGS__)), __VA_ARGS__)
230 
269 #define SIPLASPLAS_ASSERT_COMP_IMPL(a, b, op, wording) SIPLASPLAS_ASSERT_IMPL(::fmt::format( \
270  "Expected '{}' ({}) {} '{}' ({})", \
271  SIPLASPLAS_PP_STR(a), \
272  a, \
273  wording, \
274  SIPLASPLAS_PP_STR(b), \
275  b \
276  ), ((a) op (b)))
277 
296 #define SIPLASPLAS_ASSERT_EQ(a, b) SIPLASPLAS_ASSERT_COMP_IMPL(a, b, ==, "equal to")
297 
298 
317 #define SIPLASPLAS_ASSERT_NE(a, b) SIPLASPLAS_ASSERT_COMP_IMPL(a, b, !=, "not equal to")
318 
319 
338 #define SIPLASPLAS_ASSERT_BT(a, b) SIPLASPLAS_ASSERT_COMP_IMPL(a, b, > , "bigger than")
339 
340 
359 #define SIPLASPLAS_ASSERT_LT(a, b) SIPLASPLAS_ASSERT_COMP_IMPL(a, b, < , "less than")
360 
361 
380 #define SIPLASPLAS_ASSERT_BE(a, b) SIPLASPLAS_ASSERT_COMP_IMPL(a, b, >=, "bigger or equal to")
381 
382 
401 #define SIPLASPLAS_ASSERT_LE(a, b) SIPLASPLAS_ASSERT_COMP_IMPL(a, b, <=, "less or equal to")
402 
415 #define SIPLASPLAS_ASSERT_TRUE(...) SIPLASPLAS_ASSERT_IMPL(::fmt::format( \
416  "Expected '{}' to be true. Got false instead", \
417  SIPLASPLAS_PP_STR((__VA_ARGS__)) \
418  ), __VA_ARGS__)
419 
432 #define SIPLASPLAS_ASSERT_FALSE(...) SIPLASPLAS_ASSERT_IMPL(::fmt::format( \
433  "Expected '{}' to be false. Got true instead", \
434  SIPLASPLAS_PP_STR((__VA_ARGS__)) \
435  ), !(__VA_ARGS__))
436 
445 #define SIPLASPLAS_STATICASSERT_EQ(expr, expect) \
446  static_assert((expr) == (expect), "Expected equal values")
447 
456 #define SIPLASPLAS_STATICASSERT_NE(expr, expect) \
457  static_assert((expr) != (expect), "Expected non equal values")
458 
467 #define SIPLASPLAS_STATICASSERT_BT(expr, expect) \
468  static_assert((expr) > (expect), "Expected first operand bigger than the second")
469 
478 #define SIPLASPLAS_STATICASSERT_LT(expr, expect) \
479  static_assert((expr) < (expect), "Expected first operand less than the second")
480 
489 #define SIPLASPLAS_STATICASSERT_BE(expr, expect) \
490  static_assert((expr) >= (expect), "Expected first operand bigger or equal than the second")
491 
500 #define SIPLASPLAS_STATICASSERT_LE(expr, expect) \
501  static_assert((expr) <= (expect), "Expected first operand less or equal than the second")
502 
510 #define SIPLASPLAS_STATICASSERT_TRUE(expression) \
511  static_assert((expression), "Expected true expression, got false instead")
512 
520 #define SIPLASPLAS_STATICASSERT_FALSE(expression) \
521  static_assert((expression), "Expected false expression, got true instead")
522 
523 #endif // SIPLASPLAS_UTILITY_ASSERT_HPP
DummyAssertExpression & onFailure(Function)
Does nothing.
Definition: assert.hpp:168
Definition: canary_allocator.hpp:7
AssertExpression & operator()(String &&messageBody, Args &&... args)
Adds detailed information to the assertion report. Equivalent to detail().
Definition: assert.hpp:125
Represents an assertion error.
Definition: assert.hpp:26
Represents an assert expression when SIPLASPLAS_ASSERT() macros are disabled.
Definition: assert.hpp:155
DummyAssertExpression & operator()(String &&, Args &&...)
Does nothing. Equivalent to detail().
Definition: assert.hpp:192
Implements a siplasplas assertion.
Definition: assert.hpp:43
AssertExpression & detail(String &&messageBody, Args &&... messageArgs)
Adds detailed information to the assertion report.
Definition: assert.hpp:115
DummyAssertExpression & detail(String &&, Args &&...)
Does nothing.
Definition: assert.hpp:183