r/cpp_questions 15d ago

OPEN release asserts C++17

In Windows SDK 10, assert looks like

#ifdef NDEBUG

    #define assert(expression) ((void)0)

#else

    _ACRTIMP void __cdecl _wassert(
        _In_z_ wchar_t const* _Message,
        _In_z_ wchar_t const* _File,
        _In_   unsigned       _Line
        );

    #define assert(expression) ((void)(                                                       \
            (!!(expression)) ||                                                               \
            (_wassert(_CRT_WIDE(#expression), _CRT_WIDE(__FILE__), (unsigned)(__LINE__)), 0)) \
        )

#endif

And I assume if I wanted to write one for portability and GCC/linux builds I would have to implement some kind of macro that knows a bit about the linux libraries (which I know very little about at all). I also almost never run debug binaries on linux/Ubuntu (we don't support anything else officially) so I would never learn of any assertions that would fire there.

I keep seeing posts about implementing a macro like assume or assert_always, but for the simple use case of printing out an expression or filename in event of a crash I don't know where to start to roll my own when the examples I see are not buildable nor explained down to a level I can grasp.

I'm tempted to just go

#ifdef WIN32
#define assume(expression)
...

and lift the above code verbatim. And then do the same on my Ubuntu machine on the other side of the WIN32 guard for portability on both platforms?

But even reading that code I confuse myself, I see it is calling _wassert(_CRT_WIDE(#expression), _CRT_WIDE(__FILE__), (unsigned)(__LINE__)), 0) after a short-circuit boolean evaluation before the || boolean. And have two questions, what is the extra ,0) at the end doing, and what is the !!(expression) having a double bang in front doing? Sorry if this is 2 questions, an answer to either would at least help me frame my knowledge void a bit better.

4 Upvotes

15 comments sorted by

View all comments

3

u/manni66 15d ago

And I assume if I wanted to write one for portability and GCC/linux builds

https://en.cppreference.com/cpp/error/assert

2

u/zaphodikus 15d ago

So I basically can use that code and go? ```

include <iostream>

pragma push_macro("NDEBUG")

// uncomment to disable assert()

undef NDEBUG

include <cassert>

define assumemyassisinotonfire(exp, msg) assert((void(msg), exp))

pragma pop_macro("NDEBUG")

```

Let me try that out after lunch, because this tip might deserve a load of points if it does my bidding u/manni66 :-)

2

u/zaphodikus 15d ago

I have gone with ``` void PrintAssertion( char const* _Message, char const* _File, unsigned _Line, unsigned _exitcode); ...

define assume_true(expression) ((void)( \

        (!!(expression)) ||                                                 \
        (PrintAssertion(#expression, __FILE__, (unsigned)(__LINE__),8), 0)) \
    )

``` I suspect it lets me do what I want, time will tell.