Adding message to assert

前端 未结 8 1592
花落未央
花落未央 2020-12-12 20:36

Hallo!

I\'m looking for a way to add custom messages to assert statements. I found this questions Add custom messages in assert? but the message is static there. I w

相关标签:
8条回答
  • 2020-12-12 21:00
    #define ASSERT_WITH_MESSAGE(condition, message) do { \
    if (!(condition)) { printf((message)); } \
    assert ((condition)); } while(false)
    
    0 讨论(0)
  • 2020-12-12 21:00

    Extending on Kondrad Rudolph's answer:

    #include <iostream>
    
    #ifdef NDEBUG
    #define assert(condition, message) 0
    #else
    #define assert(condition, message)\
       (!(condition)) ?\
          (std::cerr << "Assertion failed: (" << #condition << "), "\
          << "function " << __FUNCTION__\
          << ", file " << __FILE__\
          << ", line " << __LINE__ << "."\
          << std::endl << message << std::endl, abort(), 0) : 1
    #endif
    
    void foo() {
       int sum = 0;
       assert((sum = 1 + 1) == 3, "got sum of " << sum << ", but expected 3");
    }
    
    int main () {
       foo();
    }
    

    Output is...

    Assertion failed: ((sum = 1 + 1) == 3), function foo, file foo.cpp, line 13.
    got sum of 2, but expected 3
    zsh: abort      ./a.out
    

    which is similar to what the std::assert macro outputs on my system just with the additional user defined message

    0 讨论(0)
  • 2020-12-12 21:03

    For the sake of completeness, I published a drop-in 2 files assert macro implementation in C++:

    #include <pempek_assert.h>
    
    int main()
    {
      float min = 0.0f;
      float max = 1.0f;
      float v = 2.0f;
      PEMPEK_ASSERT(v > min && v < max,
                    "invalid value: %f, must be between %f and %f", v, min, max);
    
      return 0;
    }
    

    Will prompt you with:

    Assertion 'v > min && v < max' failed (DEBUG)
      in file e.cpp, line 8
      function: int main()
      with message: invalid value: 2.000000, must be between 0.000000 and 1.000000
    
    Press (I)gnore / Ignore (F)orever / Ignore (A)ll / (D)ebug / A(b)ort:
    

    Where

    • (I)gnore: ignore the current assertion
    • Ignore (F)orever: remember the file and line where the assertion fired and ignore it for the remaining execution of the program
    • Ignore (A)ll: ignore all remaining assertions (all files and lines)
    • (D)ebug: break into the debugger if attached, otherwise abort() (on Windows, the system will prompt the user to attach a debugger)
    • A(b)ort: call abort() immediately

    You can find out more about it there:

    • blog post
    • GitHub project

    Hope that helps.

    0 讨论(0)
  • 2020-12-12 21:06

    going along with Konrad Rudolf's answer you can do it a bit more concise with

    #include <assert.h>
    #include <stdio.h>
    #define ASSERT(condition,...) assert( \
        condition|| \
        (fprintf(stderr,__VA_ARGS__)&&fprintf(stderr," at %s:%d\n",__FILE__,__LINE__)) \
    );
    

    which also works in C,

    it works using the general idea from some of the answers to the question you linked, but the macro allows it to be a little more flexible

    0 讨论(0)
  • 2020-12-12 21:10

    You are out of luck here. The best way is to define your own assert macro.

    Basically, it can look like this:

    #ifndef NDEBUG
    #   define ASSERT(condition, message) \
        do { \
            if (! (condition)) { \
                std::cerr << "Assertion `" #condition "` failed in " << __FILE__ \
                          << " line " << __LINE__ << ": " << message << std::endl; \
                std::terminate(); \
            } \
        } while (false)
    #else
    #   define ASSERT(condition, message) do { } while (false)
    #endif
    

    This will define the ASSERT macro only if the no-debug macro NDEBUG isn’t defined.

    Then you’d use it like this:

    ASSERT((0 < x) && (x < 10), "x was " << x);
    

    Which is a bit simpler than your usage since you don’t need to stringify "x was " and x explicitly, this is done implicitly by the macro.

    0 讨论(0)
  • 2020-12-12 21:18

    There are some old tricks to include messages without writing your own routines:

    The first is this:

    bool testbool = false;
    assert(("this is the time", testbool));
    

    There is also:

    bool testbool = false;
    assert(testbool && "This is a message");
    

    The first one works, because the inside parens expression result is the value of 'testbool'. The second one works, because the value of the string is going to be non-zero.

    0 讨论(0)
提交回复
热议问题