Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

Its pretty easy for me to guarantee that my asserts will all always be run via NDEBUG. I can't make that same guarantee for contracts
 help



> Its pretty easy for me to guarantee that my asserts will all always be run via NDEBUG.

That's the opposite of what NDEBUG does. https://en.cppreference.com/cpp/error/assert

Critical bit:

> 1) If NDEBUG is defined as a macro name at the point in the source code where <cassert> or <assert.h> is included, the assertion is disabled: assert does nothing.

It also is impossible to guarantee it unless you're the only one compiling the program. If you've built a library that others can build and relied on asserts executing for your library to be correct, you wrote a bad library.

EDIT: Neither asserts nor these C++26 contract features should be used in a way that requires that they be executed. If you do, you're using them wrong because it is valid for someone to disable them as runtime checks. If the code must run, you should use some other mechanism, I'd recommend an if statement.


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.


That's not what the C/C++ spec says people can rely on with assert/NDEBUG. Like don't get me wrong, you can do what you want, but you can and will break code in ways that introduce memory unsafety with this approach

I dunno, if a library author is toggling flags that control the nature of the end user's build that seems like tempting fate to me. How do you justify such interference?

To my mind the extent of the contract is that if the user has set NDEBUG then you can assume that assert will be a noop. I don't think you as a library author can make any assumptions about what happens if you set the flag yourself.


You absolutely can make assumptions about what happens if you set the flag, and the spec guarantees that you can!

There's no difference between the flag being set/unset by your build system, and #define-ing or #undef-ing the symbol in code


> 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.

This is totally backward. It's literally not any standard practice I have ever seen. In fact, it is an anti-practice. If you go around re-#defining standard library macros then you get what you deserve, and get no sympathy from me.

And it seems completely sensible that if I'm writing a C++ library that it's header files should include assert.h, and use assert()'s in its inline functions. And you will get no sympathy from me if you break my code by redefining the library behavior of assert().


So basically you didn't bother to look and then blindly declared it an anti-practice?

What exactly would you like me to look at that I haven't looked at already?

I don't know if it's good practice but I replace assert and assert.h with my own code (you just have to make sure to make the necessary platform specific calls in your replacement headers). So I always know exactly how assert will behave in my own codebase even when invoked by a library.

It's worth noting that the motivation for the above was poorly written libraries that hardcode the use of the builtin assert. So I agree with you completely on that point.

That said I've never been particularly impressed with how assert is defined by the standard and now somehow contracts appear set to be even worse.


Now you know. It's VERY bad practice.

I don't see how. It's certainly not encouraged but then I'm doing it to work around the bad practice of others so what do you expect?

Why do you not simply define your OWN version of assert with a different name?

It's very bad practice because you have altered the behavior of the standard library.




Consider applying for YC's Winter 2027 batch! Applications are open till November 2.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: