Line data Source code
1 : #pragma once 2 : 3 : #include <iostream> 4 : 5 : // Based on the standard paper P0627r0 (see 6 : // http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0627r0.pdf) 7 : #if defined(_MSC_VER) 8 : #define ELSA_UNREACHABLE() __assume(false); 9 : #elif defined(__GNUC__) or defined(__clang__) 10 : // All gcc/clang compilers supporting c++17 have __builtin_unreachable 11 : #define ELSA_UNREACHABLE() __builtin_unreachable() 12 : #else 13 : #include <exception> 14 : #define ELSA_UNREACHABLE() std::terminate() 15 : #endif 16 : 17 : namespace elsa::detail 18 : { 19 : void assert_msg(const char* expr_str, bool expr, const char* file, int line, const char* msg); 20 : } // namespace elsa::detail 21 : 22 : /* 23 : implementation of ENSURE - which is like an assert but "extensible" 24 : ENSURE(condition) 25 : ENSURE(condition, errormessage) 26 : 27 : currently calls assert_msg above. 28 : alternatively we could throw a backtrace capturing elsa-exception here. 29 : */ 30 : #ifndef ENSURE 31 : 32 57531534 : #define ELSA_EXPRTEXT(expr) #expr 33 : 34 : #define ENSURE(...) \ 35 57531534 : do { \ 36 57531534 : ::elsa::detail::assert_msg(ELSA_EXPRTEXT(ELSA_ENS_FIRST(__VA_ARGS__)), \ 37 57531534 : ELSA_ENS_FIRST(__VA_ARGS__), __FILE__, __LINE__, \ 38 57531534 : ELSA_ENS_REST(__VA_ARGS__)); \ 39 57531534 : } while (0) 40 : 41 : /* 42 : * expands to the first argument 43 : * Modified for MSVC using the technique by Jeff Walden 44 : * https://stackoverflow.com/a/9338429 45 : */ 46 57531534 : #define ELSA_PP_GLUE(macro, args) macro args 47 57531534 : #define ELSA_ENS_FIRST(...) ELSA_PP_GLUE(ELSA_ENS_FIRST_HELPER, (__VA_ARGS__, throwaway)) 48 57531534 : #define ELSA_ENS_FIRST_HELPER(first, ...) (first) 49 : 50 : /* 51 : * Standard alternative to GCC's ##__VA_ARGS__ trick (Richard Hansen) 52 : * http://stackoverflow.com/a/11172679/4742108 53 : * 54 : * If there's only one argument, expands to 'nullptr' 55 : * If there is more than one argument, expands to everything but 56 : * the first argument. Only supports up to 2 arguments but can be trivially expanded. 57 : * 58 : * We could extend this to support arbitrary assert message formatting, with streams, ... 59 : */ 60 : #define ELSA_ENS_REST(...) \ 61 57531534 : ELSA_PP_GLUE(ELSA_ENS_REST_HELPER(ELSA_ENS_NUM(__VA_ARGS__)), (__VA_ARGS__)) 62 : #define ELSA_ENS_REST_HELPER(qty) ELSA_ENS_REST_HELPER1(qty) 63 : #define ELSA_ENS_REST_HELPER1(qty) ELSA_ENS_REST_HELPER2(qty) 64 : #define ELSA_ENS_REST_HELPER2(qty) ELSA_ENS_REST_HELPER_##qty 65 57531534 : #define ELSA_ENS_REST_HELPER_ONE(first) nullptr 66 : #define ELSA_ENS_REST_HELPER_TWOORMORE(first, ...) __VA_ARGS__ 67 : #define ELSA_ENS_NUM(...) ELSA_ENS_NUM_IMPL((__VA_ARGS__, TWOORMORE, ONE, throwaway)) 68 : #define ELSA_ENS_NUM_IMPL(args) ELSA_ENS_SELECT_2ND args 69 : #define ELSA_ENS_SELECT_2ND(a1, a2, a3, ...) a3 70 : #endif // ENSURE 71 : 72 57531534 : #define ELSA_VERIFY ENSURE 73 : #define ELSA_TODO() ELSA_VERIFY(false, "TODO")