Adding message to assert

前端 未结 8 1593
花落未央
花落未央 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:23

    A better alternative is to teach the debugger to stop on assert when it fails, then you could examine not only the x value but any other information including call stack. Perhaps, this is what you are really looking for. Sample implementation is mentioned here Ways to show your co-programmers that some methods are not yet implemented in a class when programming in C++

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

    Yes, this is possible.

    To enable expression like better_assert((0 < x) && (x < 10), std::string("x was ") + myToString(x));, we are supposed to have a corresponding macro in a form of

    #define better_assert(EXPRESSION, ... ) ((EXPRESSION) ? \
    (void)0 : print_assertion(std::cerr, \
    "Assertion failure: ", #EXPRESSION, " in File: ", __FILE__, \ 
    " in Line: ", __LINE__ __VA_OPT__(,) __VA_ARGS__))
    

    in which print_assertion is a proxy function to do the assertion. When the EXPRESSION is evaluated false, all the debug information, the __VA_ARGS__, will be dumped to std::cerr. This function takes arbitrary numbers of arguments, thus we should implement a variadic templated function:

    template< typename... Args >
    void print_assertion(std::ostream& out, Args&&... args)
    {
        out.precision( 20 );
        if constexpr( debug_mode )
        {
            (out << ... << args) << std::endl;
            abort();
        }
    }
    

    In the previous implementation, the expression (out << ... << args) << std::endl; make use of fold expression in C++17 (https://en.cppreference.com/w/cpp/language/fold); the constant expression debug_mode is related to the compilation options passed, which is can be defined as

    #ifdef NDEBUG
        constexpr std::uint_least64_t debug_mode = 0;
    #else
        constexpr std::uint_least64_t debug_mode = 1;
    #endif
    

    It also worth mentioning that the expression if constexpr( debug_mode ) makes use of constexpr if (https://en.cppreference.com/w/cpp/language/if) imported since C++17.

    To wrap everything up, we have:

    #ifdef NDEBUG
        constexpr std::uint_least64_t debug_mode = 0;
    #else
        constexpr std::uint_least64_t debug_mode = 1;
    #endif
    
    template< typename... Args >
    void print_assertion(std::ostream& out, Args&&... args)
    {
        out.precision( 20 );
        if constexpr( debug_mode )
        {
            (out << ... << args) << std::endl;
            abort();
        }
    }
    #ifdef better_assert
    #undef better_assert
    #endif
    #define better_assert(EXPRESSION, ... ) ((EXPRESSION) ? (void)0 : print_assertion(std::cerr, "Assertion failure: ",  #EXPRESSION, " in File: ", __FILE__, " in Line: ",  __LINE__ __VA_OPT__(,) __VA_ARGS__))
    

    A typical test case demonstrating its usage can be:

    double const a = 3.14159265358979;
    double const b = 2.0 * std::asin( 1.0 );
    better_assert( a==b, " a is supposed to be equal to b, but now a = ", a, " and b = ", b );
    

    This will produce something error message like:

    Assertion failure: a==b in File: test.cc in Line: 9 a is supposed to be equal to b, but now a = 3.1415926535897900074 and b = 3.141592653589793116
    [1]    8414 abort (core dumped)  ./test
    

    And the full source code is available in this repo: https://github.com/fengwang/better_assert

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