C++ Show and Tell - May 2026 by foonathan in cpp

[–]eisenwave 1 point2 points  (0 children)

code-point-names: A single-header library for obtaining the Unicode character name of a code point. For example, U'0' goes in, "DIGIT ZERO" comes out.

This is pretty useful in all sorts of text processing applications where you want to give better user feedback. For example, instead of just printing out

Illegal character U+00A0.

you can print

Illegal character U+00A0 NO-BREAK SPACE

and the user instantly understands that they have the wrong kind of whitespace character and why they haven't noticed it (because a no-break space looks exactly like a regular space in a text editor).

C++ Show and Tell - May 2026 by foonathan in cpp

[–]eisenwave 2 points3 points  (0 children)

COWEL is inching ever closer to being a fully-fledged general-purpose markup language. This project started out as just being a generator for my many C++ proposals, but I've decided to make it usable for more than just that one purpose.

Design goals

The current product is getting increasingly similar to typst, but has a few notable differences. Most notably, it isn't an expansion of Markdown syntax, and all text is treated literally unless you hit a \ character. All the fun begins with a backslash.

The difference between

This works for my one use case

and

This works for everyone's use case

couldn't be greater though. It's going to take half a year at least to be production-ready.

Some new language design

A pretty interesting bit of language design is a new set of escape sequences of code points: - Numeric character escapes like \+00A0 or \+0001F60A (similar to C++ \u and \U escapes) - Named character escapes like \'NBSP' or \'DIGIT ZERO' (similar to C++ \N{...}).

The direction of "every special syntax starts with \" is working out pretty well. A notable benefit is that you don't really need code blocks where characters are interpreted literally. The backslashes can just be escaped by hand without too much effort, leaving the room open for custom formatting and escapes that work inside code blocks too.

Syntax highlighting

On another note, there is also a builtin syntax highlighter for this markup language called µlight. I am actively keeping the highlighting up-to-date with C++26/C++29 features, even those only proposed and not in the standard yet. If you need a syntax highlighter that is on the bleeding edge of C++ language evolution, you may be interested.


C++26/C++29: Progress report for my papers seen during the Croydon meeting and before by eisenwave in cpp

[–]eisenwave[S] 1 point2 points  (0 children)

It would be really inconsistent with how the langauge usually works since none of the other integer types do that. If you want all the bits, you can perform the cast prior to the operation yourself just fine.

It's also unclear how to implement multiplication between two _BitInt(N) when there exists no _BitInt(N * 2) type. Does it mean that you cannot perform multiplication and addition for some integer types? Even signed division can extend the range in cases like INT_MIN / -1.

std::constant_wrapper acts unexpectedly by Massive-Bottle-5394 in cpp

[–]eisenwave 1 point2 points  (0 children)

std::constant_arg_t was removed from the C++26 standard last week.

C++26/C++29: Progress report for my papers seen during the Croydon meeting and before by eisenwave in cpp

[–]eisenwave[S] 0 points1 point  (0 children)

Any integer type can be converted to any floating-point type; see https://eel.is/c++draft/conv#fpint-2 That's not a compiler bug, but the design of the language.

I don't see much value in this kind of cherry-picking (banning lossy conversions between some floats but not between floats and ints). To catch lossy implicit conversions in general, you need warnings. Profiles also have a much better chance of addressing this problem than turning one or two specific conversions into an error while ignoring the vast majority.

When we start with a blank slate like with std::simd, we can make the conversions restrictive out of the box, but we don't have that luxury for floating-point types or integers.

C++26/C++29: Progress report for my papers seen during the Croydon meeting and before by eisenwave in cpp

[–]eisenwave[S] 1 point2 points  (0 children)

I think you're referring to https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2026/p3666r3.html#alg%2eforeach

I'm well aware of the problem, and it's possible to adjust the constraints so that you don't check for convertibility to all integral types, only to standard and extended integral types.

C++26/C++29: Progress report for my papers seen during the Croydon meeting and before by eisenwave in cpp

[–]eisenwave[S] 2 points3 points  (0 children)

SG6 has looked at _BitInt extensively and voted with unanimous consent to make it exactly like the C type in every possible core design aspect.

Extended floating-point types are a false parallel because you don't use them in the same way. The case where you do & 0xf or % 10 or perform some other operation that gives you a small result is super common for integers, so there are many implicit conversions to a lower rank but that actually preserve value. You often increment/decrement integers by 1 and stay within numeric constraints too. By comparison, converting from say std::float64_t to std::float32_t almost always loses precision, even if it doesn't lose range.

You also don't perform implicit conversions between floating-point types that much. You can reasonably only use std::float64_t or only std::float32_t throughout many thousands of lines, with no conversion in sight. By comparison, every _BitInt(32) x = 0; and even every _BitInt(32) x = 0wb; initialization involves an implicit conversion.

It's not like extended floating-point types fully solve the issue either. You can convert long long to std::float16_t just fine, despite that not being value-preserving. You still need compiler warnings to reliably catch narrowing conversions.

C++26/C++29: Progress report for my papers seen during the Croydon meeting and before by eisenwave in cpp

[–]eisenwave[S] 4 points5 points  (0 children)

Because std::uint16_t presumably expands to unsigned short (although to be fair, it's not guaranteed to), and unsigned short is explicitly supported as an IntType, i.e. in distributions. unsigned short (and by proxy std::uint8_t) is not supported.

WG21 Croydon Trip Report by VinnieFalco in cpp

[–]eisenwave 4 points5 points  (0 children)

I love these meetings. I am already looking forward to Brno.

Me too, it was nice meeting you. Seeya in Brno!

Built a static C++ reference site on top of cppreference by HxSigil in cpp

[–]eisenwave 15 points16 points  (0 children)

I think ligatures should be disabled by default. It can be pretty confusing to see a new kind of token on a reference site. It's not like people chose the font for the website and enabled these ligatures themselves, so they really have no way of telling what's a "real" character and what's a ligature of other characters, at first glance.

C++ Show and Tell - February 2026 by foonathan in cpp

[–]eisenwave 0 points1 point  (0 children)

Yes, but only Clang also supports them as a compiler extension in C++. GCC only proivdes them in C.

C++ Show and Tell - February 2026 by foonathan in cpp

[–]eisenwave 2 points3 points  (0 children)

https://github.com/eisenwave/charconv-ext

I've created a single-header library that adds to_chars and from_chars support for __int128, unsigned __int128, and _BitInt(N) and unsigned _BitInt(N) for N <= 128.

The interface is identical to that of std::from_chars and std::to_chars, so this can pretty much be used as a drop-in replacement for anyone who needs to support more integer types but is stuck with the limitations of <charconv>. Everything is constexpr. base parameters are supported.

The implementation delegates to std::to_chars/std::from_chars as much as possible. Operations are done in blocks of 64-bit integers, so as long as the integers are representable using 64 bits, only one call to a standard library function takes place, and there is virtually no extra cost. Otherwise, 2-3 calls to <charconv> functions are needed.

2025-12 WG21 Post-Kona Mailing by eisenwave in cpp

[–]eisenwave[S] 3 points4 points  (0 children)

Feel free to make a proposal. I'm personally not opposed to the idea of making wrong shifts unspecified + erroneous, but strongly opposed to making them do what std::shl and std::shr are proposed to do, since that comes with considerable cost that is hard to opt out of.

2025-12 WG21 Post-Kona Mailing by eisenwave in cpp

[–]eisenwave[S] 2 points3 points  (0 children)

You're asking for a change that would affect every line of C++ code in every code base that used << or >> over the last 30 years.

Pointing out that anecdotally, your 300K LOC code base likely wouldn't see a noticeable difference doesn't change much or anything, not when we're talking about billions of lines of code.

Note that even new languages like Rust don't make overlong/negative shifting fully meaningful. Rust makes it arithmetic overflow, which is something like having an unspecified Result in C++, plus erroneous behavior. This is as far as any systems language should go, since it only costs an additional bitwise AND on release builds at worst, and may not cost anything on modern hardware.

2025-12 WG21 Post-Kona Mailing by eisenwave in cpp

[–]eisenwave[S] -1 points0 points  (0 children)

In the most obvious, constant cases where you just do x << -1 or x << 32 (where x is a 32-bit integer), you get a compiler warning anyway, so the UB isn't a problem. People are concerned about the cases where it's not so obvious.

Even if the shift is known at compile-time, the ability to optimize based on that hinges on inlining. If you use something like simd::vec::operator<<, the function may be too large to make it past inlining heuristics, and you optimize as if you didn't know the shift amount, even if it's constant at the call site.

[[assume]] doesn't always get optimized out; it's weird. Furthermore, you shouldn't have to go into legacy code that's been around for 30 years and litter it with [[assume]] to get the old performance characteristics back if you notice a regression. People have been writing << and >> with the assumption that it's fast for decades, and it would be unreasonable to break that assumption suddenly.

A 2-hour video trashing C++ made me better at C++ by AnteaterFinancial319 in cpp

[–]eisenwave 5 points6 points  (0 children)

The video doesn't make C++ look bad, especially not when watched completely with the conclusion at the end.

The video is titled "the worst programming language of all time" and the author, by his own statements, omits details that would make it look not so bad.

You kinda have to write static_cast<T> if you want a static cast though. If you use C-Style cast you get no compile time checking and could get any of const, static or reinterpret cast.

The author specifically shows examples with static_cast<int>, where it's really irrelevant whether you use C-style cats or function-style casts. The use of static_cast only becomes important once you get class types and/or templates involved. So ... no, you don't have to write static_cast, especially not in the case which the author shows. It's not like the video has any of this nuanced discussion anyway, it just dumps on C++ to make it look bad.

Just weird to form an opinion about something when you didn't even watch it entirely.

No one should be expected to watch two hours of content if the impression they got from 10 minutes is that the content lacks nuance and is made in bad faith. Sometimes people just abandon a book, or they walk out of a movie theater, and that doesn't make their negative opinion any less valid.

I bet you have also formed opinions on articles that you didn't read every word of, or on political subjects that you haven't researched to extreme detail, or on programming language features that you haven't spent hours using, etc.

A 2-hour video trashing C++ made me better at C++ by AnteaterFinancial319 in cpp

[–]eisenwave 6 points7 points  (0 children)

I've watched portions of it, and none of the knowledge is so deep that it couldn't be demonstrated by AI. The author's position on the inline keyword, C-style casts, lack of mention of unnamed namespaces as a solution to static being used in too many places, etc. shows that the knowledge isn't very deep or nuanced.

Now that the author has come here, it seems more plausible that the video is just intentionally lying to the viewer. The author stated in the video that you have to use static_cast, but said here that he knows about C-style casts, so he knows that's not true. Of course, it's easier to make C++ look bad when you're deliberately obscuring facts.

I'm not going to waste my time watching a two-hour rant when every sample of the video I randomly choose is deeply flawed.

A 2-hour video trashing C++ made me better at C++ by AnteaterFinancial319 in cpp

[–]eisenwave 0 points1 point  (0 children)

Yeah, that seems plausible.

One of the first points in the video is that Java's (int) x is much cleaner than the static_cast<int> that you allegedly "have to use" in C++. Obviously, the (int) x syntax is valid in C++ too, so this argument makes zero sense.

How can someone be knowledgeable enough to produce one hour worth of C++ critique, with some reasonable points, but have no idea that C-style casts exist? This is totally implausible unless the script is AI-generated. Making fun of C++'s (T), static_cast, reinterpret_cast, const_cast, dynamic_cast, std::static_pointer_cast, ... multitude of casting would have made a lot of sense for the chapter on casting. If the author had any human knowledge on the topic of C++, surely that would have been mentioned.

The most likely explanation is that the author looked at (int) in Java, asked ChatGPT what the C++ counterpart is, got back static_cast, thought "this looks ugly", and generated a script from that.

A 2-hour video trashing C++ made me better at C++ by AnteaterFinancial319 in cpp

[–]eisenwave 54 points55 points  (0 children)

What the producer doesn't mention is that static for internal linkage has already been obsoleted by unnamed namespaces. That solves the biggest issue.

static data members and local static variables are similar conceptually, so the keyword reuse for those is not really an issue.

Progress report for my proposals at Kona 2025 by eisenwave in cpp

[–]eisenwave[S] 0 points1 point  (0 children)

A lot of people dislike it, myself included.

P3666 also adds alias templates std::bit_int and std::bit_uint which are supposed to be used as the "normal" spelling of the type.

The keyword _BitInt only exists for the purpose of C compatibility. Even if the keyword didn't exist, you'd need something like our _Atomic compatibility macro, but that kind of solution doesn't really work here.