Add custom messages in assert?

C++Assert

C++ Problem Overview


Is there a way to add or edit the message thrown by assert? I'd like to use something like

assert(a == b, "A must be equal to B");

Then, the compiler adds line, time and so on...

Is it possible?

C++ Solutions


Solution 1 - C++

A hack I've seen around is to use the && operator. Since a pointer "is true" if it's non-null, you can do the following without altering the condition:

assert(a == b && "A is not equal to B");

Since assert shows the condition that failed, it will display your message too. If it's not enough, you can write your own myAssert function or macro that will display whatever you want.

Solution 2 - C++

Another option is to reverse the operands and use the comma operator. You need extra parentheses so the comma isn't treated as a delimiter between the arguments:

assert(("A must be equal to B", a == b));

(this was copied from above comments, for better visibility)

Solution 3 - C++

Here's my version of assert macro, which accepts the message and prints everything out in a clear way:

#include <iostream>

#ifndef NDEBUG
#   define M_Assert(Expr, Msg) \
    __M_Assert(#Expr, Expr, __FILE__, __LINE__, Msg)
#else
#   define M_Assert(Expr, Msg) ;
#endif

void __M_Assert(const char* expr_str, bool expr, const char* file, int line, const char* msg)
{
    if (!expr)
    {
        std::cerr << "Assert failed:\t" << msg << "\n"
            << "Expected:\t" << expr_str << "\n"
            << "Source:\t\t" << file << ", line " << line << "\n";
        abort();
    }
}

Now, you can use this

M_Assert(ptr != nullptr, "MyFunction: requires non-null argument");

And in case of failure you will get a message like this:

> Assert failed:  MyFunction: requires non-null argument > > Expected: ptr != nullptr > > Source: C:\MyProject\src.cpp, line 22

Nice and clean, feel free to use it in your code =)

Solution 4 - C++

BOOST_ASSERT_MSG(expre, msg)

http://www.boost.org/doc/libs/1_51_0/libs/utility/assert.html

You could either use that directly or copy Boost's code. Also note Boost assert is header only, so you could just grab that single file if you didn't want to install all of Boost.

Solution 5 - C++

As zneak's answer convolutes the code somewhat, a better approach is to merely comment the string text you're talking about. ie.:

assert(a == b); // A must be equal to B

Since the reader of the assert error will look up the file and line anyway from the error message, they will see the full explanation here.

Because, at the end of the day, this:

assert(number_of_frames != 0); // Has frames to update

reads better than this:

assert(number_of_frames != 0 && "Has frames to update");

in terms of human parsing of code ie. readability. Also not a language hack.

Solution 6 - C++

assert is a macro/function combination. you can define your own macro/function, using __FILE__, __BASE_FILE__, __LINE__ etc, with your own function that takes a custom message

Solution 7 - C++

If the assert is done within a class, an alternative approach is to call a static predicate function with a self-describing name. If the assertion fails, the message will already contain the predicate's pretty and self-describing name.

E.g.:

static bool arguments_must_be_ordered(int a, int b) {return a <= b;}

void foo(int a, int b)
{
    assert(arguments_must_be_ordered(a, b));
    // ...
}

You may even want to make that predicate function public so that the class' user can verify the precondition themselves.

Even if assert is not disabled for release builds, the compiler will likely inline the predicate if it's fairly trivial.

The same approach can be used for complex if conditions needing a comment. Instead of a comment, just call a self-describing predicate function.

Solution 8 - C++

You could also just write your own custom assert function. A very simple example:

bool print_if_false(const bool assertion, const char* msg) {
    if(!assertion) {
        // endl to flush
        std::cout << msg << std::endl;
    }
    return assertion;
}

int main()
{
    int i = 0;
    int j = 1;
    assert(print_if_false(i == j, "i and j should be equal"));
    return 0;
}

play with the code.

The assertion reads Assertion print_if_false(i == j, "i and j should be equal").

Solution 9 - C++

For vc, add following code in assert.h,

#define assert2(_Expression, _Msg) (void)( (!!(_Expression)) || (_wassert(_CRT_WIDE(#_Msg), _CRT_WIDE(__FILE__), __LINE__), 0) )

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionKillrazorView Question on Stackoverflow
Solution 1 - C++zneakView Answer on Stackoverflow
Solution 2 - C++Andrei BozantanView Answer on Stackoverflow
Solution 3 - C++Eugene MagdalitsView Answer on Stackoverflow
Solution 4 - C++ZeroView Answer on Stackoverflow
Solution 5 - C++metamorphosisView Answer on Stackoverflow
Solution 6 - C++Merlyn Morgan-GrahamView Answer on Stackoverflow
Solution 7 - C++Emile CormierView Answer on Stackoverflow
Solution 8 - C++User12547645View Answer on Stackoverflow
Solution 9 - C++JichaoView Answer on Stackoverflow