Advertisement
Bisqwit

assertpp.hh

Oct 11th, 2015
490
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 2.17 KB | None | 0 0
  1. /* This header file defines a macro that works the same way as assert()
  2.  * from assert.h, except that it also allows specifying expressions
  3.  * whose values will be output alongside the failed assertion.
  4.  * Error messages will be output to std::cerr
  5.  * and the program terminated with std::terminate().
  6.  *
  7.  * Usage:
  8.  *   assertpp(condition, [<expression> [...]]);
  9.  *
  10.  * Examples:
  11.  *   assertpp(x<4);
  12.  *   assertpp(x==4,  x);
  13.  *   assertpp(vec.size() < limit,  limit, vec.size());
  14.  *   assertpp(var1==var2,  var1, var2);
  15.  *
  16.  * Copyright: (C) 2015 Joel Yliluoma, http://iki.fi/bisqwit/
  17.  * License: Creative Commons Attribution (CC-BY 1.0, 2.0 or 3.0)
  18.  */
  19.  
  20. #include <iostream>
  21. #include <exception>
  22.  
  23. #ifdef NDEBUG
  24.   #define assertpp(condition, args...)
  25. #else
  26. template<typename...>
  27. class assertpphandler
  28. {
  29.     const char* v;
  30. public:
  31.     assertpphandler(const char condstr[], const char file[], unsigned line, const char func[], const char* vars) : v(vars)
  32.     {
  33.         std::cerr << file << ':' << line << ": " << func << ": Assertion failed: " << condstr << " (";
  34.         if(*v) std::cerr << "With ";
  35.     }
  36.     void operator() () { std::cerr << ")\n"; std::terminate(); }
  37.     template<typename T, typename...U> void operator()(T&& v, U&&... rest)
  38.     {
  39.         GetVar() << std::forward<T>(v);
  40.         (*this)(std::forward<U>(rest)...);
  41.     }
  42. private:
  43.     std::ostream& GetVar()
  44.     {
  45.         int parens=0;
  46.         if(*v == ',') { std::cerr << ", "; ++v; }
  47.         while(*v == ' ' || *v == '\t' || *v == '\n' || *v == '\r' || *v == '\v') ++v;
  48.         while(*v && (*v != ',' || parens != 0))
  49.         {
  50.             if(*v == '(') ++parens; else if(*v == ')') --parens;
  51.             std::cerr << *v++;
  52.         }
  53.         return std::cerr << " = ";
  54.     }
  55. };
  56.  
  57. #ifdef __GNUC__
  58. # define assertpp(condition, ...) do { \
  59.     if(__builtin_expect(!(condition),false)) \
  60.         assertpphandler<>(#condition, __FILE__, __LINE__, __PRETTY_FUNCTION__, #__VA_ARGS__)(__VA_ARGS__); } while(0)
  61. #else
  62. # define assertpp(condition, ...) do { \
  63.     if(!(condition)) \
  64.         assertpphandler<>(#condition, __FILE__, __LINE__, __func__, #__VA_ARGS__)(__VA_ARGS__); } while(0)
  65. #endif
  66.  
  67. #endif
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement