5 ms·
C++26: A User-Friednly assert() macro
- deleted 7mo ago[deleted]
- nyc_pizzadev 7mo agoThe nice thing about assert() is you can just define your own: https://github.com/fiberfs/fiberfs/blob/7e79eaabbb180b0f1a7942b318e981293318a6da/src/core/fs/fbr_directory.c#L190 https://github.com/fiberfs/fiberfs/blob/7e79eaabbb180b0f1a79... In this case, the ability to see the actual values that triggered the assert is way more helpful.
- BoingBoomTschak 7mo agoYeah, but the macro system being so pitiful makes me long for one that allows something as magical as fiveam's is (https://github.com/lispci/fiveam/blob/e43d6c8e7da5a80d5c33e8ca018fb1619c5b0293/src/check.lisp#L113 https://github.com/lispci/fiveam/blob/e43d6c8e7da5a80d5c33e8...) instead of having to write special cases for unary and binary predicates.
- omoikane 7mo ago> (assert) doesn't follow the usual SCREAMING_SNAKE_CASE convention we associate with macros There are a few things like that, for example: https://en.cppreference.com/w/c/numeric/math/isnan https://en.cppreference.com/w/c/numeric/math/isnan - isnan is an implementation defined macro. https://en.cppreference.com/w/c/io/fgetc https://en.cppreference.com/w/c/io/fgetc - `getc` may be implemented as a macro, but often it's a function.
- nealabq 7mo agoIn C++ you should probably #include <cstdio> instead of <stdio.h> unless you have a good reason. And especially avoid #including both. <cstdio> provides the function std::getc(..) while <stdio.h> usually provides getc(..) as a macro. htons(..) and related socket-utility names are also often macros, but I'm pretty sure there is not a std::htons(..) in the C++ standard, partly because 'htons' is not an attractive name. Since it's (sometimes) a macro don't qualify its namespace like ::htons(..). A long time ago in the Microsoft C (and later C++) dev envs there were macros named "min" and "max", which I thought were terrible names for macros.
- adzm 7mo ago> A long time ago in the Microsoft C (and later C++) dev envs there were macros named "min" and "max", which I thought were terrible names for macros. Yeah, this is still in windows.h unless you #define NOMINMAX I remember having to guard against this in some inline code by surrounding the c++ calls with parenthesis, eg `(std::min)(a, b)`
- nananana9 7mo agoYep. There's tons of others as as well. 16-bit x86 enjoyers will be happy to know there are `near` and `far` macros whose primary purpose in 2026 is to break my projection matrices. And of course every Win32 function that takes strings has a macro that resolves it to either the UTF-16 or ASCII variant, so your custom CreateWindow is now a CreateWindowA, tough luck buddy. I usually wrap Windows.h in a header followed by 100 #undefs to contain the disease.
- deleted 7mo ago[deleted]
- MontagFTB 7mo agoPutting code with side effects into an assert is asking for trouble. Compile with NDEBUG set and the effects mysteriously disappear! Anything beyond an equality expression or straight boolean should be avoided.
- nyc_pizzadev 7mo agoThis is just a symptom of a bad assert() implementation, which funny enough is the standard. If you properly (void) it out, side effects are maintained. https://github.com/fiberfs/fiberfs/blob/7e79eaabbb180b0f1a7942b318e981293318a6da/src/utils/fbr_assert.h#L45 https://github.com/fiberfs/fiberfs/blob/7e79eaabbb180b0f1a79...
- omoikane 7mo agoassert() is meant to be compiled away if NDEBUG is defined, otherwise it shouldn't be called assert(). Given that assert() may be compiled away, it makes sense not to give it anything that has side effects. Abseil has the convention where instead of assert(), users call "CHECK" for checks that are guaranteed to happen at run time, or "DCHECK" for checks that will be compiled away when NDEBUG is defined. https://github.com/abseil/abseil-cpp/blob/0093ac6cac892086a6d7d09c55421a2a4c2cdb2e/absl/log/check.h#L21 https://github.com/abseil/abseil-cpp/blob/0093ac6cac892086a6... https://github.com/abseil/abseil-cpp/blob/0093ac6cac892086a6d7d09c55421a2a4c2cdb2e/absl/log/internal/check_impl.h#L39 https://github.com/abseil/abseil-cpp/blob/0093ac6cac892086a6...
- nmilo 7mo agoIf your assert compiles down to `if (condition) {}` in production then the compiler will optimize away the condition while keeping any side effects.
- IshKebab 7mo agoYeah which may not be what you want. E.g. `assert(expensive_to_compute() == 0)`. The correct way to solve this is with debug asserts (as in Rust, or how the parent described).
- throwpoaster 7mo agoassert(spellcheck(“Friednly”));
- nananana9 7mo agospellcheck.cpp:1:19: error: unexpected character <U+201C> 1 | assert(spellcheck(“Friednly”)); | ^
- throwpoaster 7mo agoTechnically correct is best correct! Touché!
- amelius 7mo agoShouldn't the preprocessor be fixed, if it trips that easily on common C++ constructs?
- tom_ 7mo agoI'm sure the standardization committee are always looking for fresh ideas!
- marginalia_nu 7mo agoPreprocessor is just doing text transformations on the sources. It's not really something that can be fixed, other than moving away from the preprocessor and putting metaprogramming capabilities into the language itself (which C++ has been doing).
- amelius 7mo agoI mean, you could extend it such that a simple comma has no special meaning. But I agree, fewer special tricks is better and that includes the preprocessor.
- deleted 7mo ago[deleted]
- semiinfinitely 7mo ago"C++47: Finally, a Standard Way to Split a String by Delimiter"
- porise 7mo agoI'm still waiting for C++ to support Unicode properly.
- einpoklum 7mo agoA standard way to split a string? Well, what's wrong with: std::views::split(my_string, delimeter) ?
- nananana9 7mo agoTemplate bloat, terrible compile errors, terrible debug build performance, 1 second of extra compile time per cpp file when you include ranges, and you can't step through it in a debugger.
- fc417fc802 7mo ago> you can't step through it in a debugger. What do you mean by that?
- einpoklum 7mo agoNone of these complaints detract from this being a terse, readable, and available using the standard library, which is what the question was about... I will agree that std::ranges is quite a jumble of templates, and has a compilation time penalty. Perhaps the use of modules will help with that somewhat.
- MathMonkeyMan 7mo agoThere's been this since 1998, likely earlier: std::vector<std::string> split(const std::string& text, char delimiter) { std::vector<std::string> parts; std::istringstream stream(text); std::string part; while (std::getline(stream, part, delimiter)) { parts.push_back(part); } return parts; }
- grokcodec 7mo agoFriedns shouldn't let Freidns post on HN without running spell check
- adzm 7mo agoOne of my favorite things from ATL/WTL was the _ASSERT_E macro which additionally converts the source expression to text for a better message to be logged
- WalterBright 7mo agoD just makes assert() part of the language: https://dlang.org/spec/expression.html#assert_expressions https://dlang.org/spec/expression.html#assert_expressions The behavior of it can be set with a compiler switch to one of: 1. Immediately halting via execution of a special CPU instruction 2. Aborting the program 3. Calling the assert failure function in the corresponding C runtime library 4. Throwing the AssertError exception in the D runtime library So there's no issue with parsing it. The compiler also understands the semantics of assert(), and so things like `assert(0)` can be recognized as being the end of the program.
- rurban 7mo agoSo you are ignoring our well beloved NDEBUG? :) Our idea of declare (optimize (speed 3) (safety 0))
- WalterBright 7mo agoD compilers have a "ramming speed" setting.
- panzi 7mo agoBut does it have a ludicrous speed setting?
- wpollock 7mo ago> assert(x > 0 && "x was not greater than zero"); Shouldn't that be "||" rather than "&&"? We want the message only if the boolean expression is false.
- puschkinfr 7mo agoNo, because the string will be implicitly converted to `true` and `(a && true) == a` (for boolean `a`), so it will only be `false` if the assertion fails. Using || would always evaluate to `true`
- deleted 7mo ago[deleted]
- wpollock 7mo agoYou're right, thanks! This works too (but I wouldn't recommend it): assert( someBooleanExpression || ! "It is false" );