Comment by 20k

4 days ago

Of course? You simply undefine NDEBUG in your library

Its trivially easy to guarantee that an assert always runs, and its well defined behaviour according to the spec. There's no reason not to if you want to use asserts in a way that guarantees that they always fire, which is a supported use case. Its common practice

There's no equivalent for contracts

> Of course?

You sound as if "my asserts will all always be run via NDEBUG" makes perfect sense and not the exact opposite of what you've expanded it to

> Its common practice

not really, no

post ++11 cpp has been moving away from preprocessor (pedagogically and culturally), so "let's force-undefine NDEBUG" trick isn't at the top of most people's minds

  • You use the status of NDEBUG to control whether or not your asserts are run. I don't understand how this is complex

    If you want to use asserts, you need to control the definition of NDEBUG. You either do this with your build system (common), or manually (slightly less common). This is literally <assert.h> 101

    The preprocessor is widely used for a variety of things when its necessary, including #includes and #defines, because there's literally no other mechanism for this. Its bizarre to say that nobody controls the definition status of NDEBUG because people don't use the preprocessor

No, it's not. Don't do that. Someone (like me) will replace assert.h wholesale and it will not behave the way you expected. Always define your own internal macro and always provide facilities for the user to override it.

  • Blindly replacing #include <assert.h> to look up something incompatible that doesn't respect NDEBUG seems like a remarkably bad idea

    • I don't see why. The user invoking the compiler should be the only one controlling NDEBUG (or its equivalent). So far the only bad idea I've run into is the occasional library author blindly importing assert.h which happily stomps all over my custom implementation.

      There's a whole host of things that libraries need to be extremely conservative about touching. Assert, threads, signals, etc.

      3 replies →

  • > Always define your own internal macro and always provide facilities for the user to override it.

    that kinda sounds even more insane and cumbersome

    • It's literally standard practice. You import assert.h unless the end user has defined mylib_assert in which case you don't import and use that instead. Failing to do this can result in all kinds of dumb problems thanks to the namespace being global.

      3 replies →