Meeting 147 - C++Builder, Rust, ULID, Show & Tell, Crow, Quantum C++
Media
Video
Podcast
Powered by RedCircle
Follow-up: Float Toy
Ivor Hewitt told me about a cool website called Float Toy. It allows you to visualise the binary representation of floating-point numbers of various sizes. You can toggle individual bits in sign, exponent and mantissa parts and see how it affects the represented value.
Celebrating 25 Years of C++Builder
Embarcadero posted an article celebrating 25 years of C++ Builder. For those like me who remember Turbo C and C++ fondly, this is a bittersweet article reminding how a great product can turn into something very few people use because of the inept owners. Thy made C++ Builder v1 freely downloadable for nostalgic value, and there is also a free community version of the modern C++ Builder 11 which is still Windows-only and has a limit of $5000 revenue or more than 5 developers per company before you need to pay big bucks. It supports FireMonkey, Embarcadero’s cross-platform GUI framework, but for some reason doesn’t use it to actually be cross-platform.
There is a link to a retrospective and a magazine review from 1997 of Borland C++ Builder v1, including the non-standard C++ features added by Borland in order to support RAD capabilities previously available in Delphi only.
Here is a quote that demonstrates what Embarcadero thinks modern cross-platform support means:
The toolchain has a long history of supporting non-Windows platforms: did you know that Borland shipped C++ compilers for Nokia and Symbian mobile devices? Today you can use C++Builder for Windows and iOS.
I’m a little bitter and sad, as you can tell. I learnt programming with Turbo Pascal and Turbo C++. Borland C++ was my favourite IDE (before I switched to Microsoft C++ 1.52c for better Windows support). I would have liked a modern affordable cross-platform Borland-style C++ IDE. Oh well, there is always CLion, I guess.
C++ and Rust interoperability
An article was published on the Tetrane blog describing the current state of Rust and C++ interoperability. The article explains all the available options in detail, including code snippets, but for a short summary let’s read a comment on the Reddit thread by the original poster:
The post proposes 3 approaches based on 3 available libraries in the Rust ecosystem:
- bindgen
- Start from the C or C++ headers of a C/C++ library and generate Rust code that exposes functions able to call the C/C++ library. Then you can just link with this library (statically or dynamically) and call its functions! It is automatic, but it doesn’t attempt to reconcile the differences of concepts between C++ and Rust, and more importantly, it doesn’t attempt to translate what C++ and Rust have in common (iterators, vectors,
string
,unique_ptr
,shared_ptr
, …), so it is best suited for very “C-like” libraries.- cpp
- Uses Rust’s macro system to let you write C++ inline inside of your Rust. The C++ snippets are then compiled by a C++ compiler, and the Rust code to call them using the C ABI is generated. Since the C++ snippets are C++, you can directly call other C++ libs from the C++ snippets. However the boundary between C++ and Rust remains somewhat low-level with this solution (it has native understanding of
unique_ptr
s but that’s pretty much it).- cxx
- Uses Rust’s macro system to let you declare a special Rust module containing items (types, functions) to be either shared (understood by both C++ and Rust, and passed by value between the languages) or opaquely exposed from one language to the other (you’ll need to manipulate the type behind a pointer when on the other language). This approach is nice because it pre-binds for you some C++/Rust standard types (vectors, strings) and concept (exceptions and Rust’s
Result
type).At the basic levels, all three libraries are built upon the C ABI/API, since it is the common language that both Rust and C++ understand. In cxx however you don’t really see the use of the basic C API since some higher-level concepts are translated between C++ and Rust.
I read that Microsoft is exploring Rust for some of their code bases, wonder what they’ll use if they need C++ interop.
Minimum viable declarative GUI in C++
Jean-Michaël Celerier wrote an article that introduces a minimal declarative C++ GUI library. Like, really minimal, where declaring a struct is enough to define a user interface. Later this declaration is included in another ‘magical’ file which produces the declared UI. The resulting interface can be rendered by Qt via QML or another backend, like Nuklear (a C-based immediate mode UI engine).
An example UI declaration is on GitHub.
In the Reddit thread, people are generally impressed, until they discover all the macros the author had to add to improve the syntax.
Also, the code is under GPLv3, so be careful not to remember any of it or you’ll have to open-source your brain.
ULID: Universally Unique Lexicographically Sortable Identifier
ULID is a replacement for UUID that is human-readable and lexicographically sortable. It is encoded in 26-character string (as opposed to 36-character UUID), uses base32 encoding for readability (no ambiguous characters), and doesn’t use special characters, which makes it URL-safe.
Implementations exist in many languages, including an MIT-licensed C++ version.
Next time you need a UUID in your software, see if ULID is a better fit for your needs.
C++ for mathematicians
A redditor asks what are good books about mathematical programming in C++. Some suggestions from the thread:
- Numerical Recipes – you can read the ebook for free online, including source code.
- What Every Computer Scientist Should Know About Floating-Point Arithmetic by David Goldberg is a classic article I mentioned many times.
- Object-Oriented Programming for Scientific Computing (University of Heidelberg) with lecture notes and slides.
Crow web framework
A redditor writes:
A year and a half ago I picked up an abandoned C++ web Framework, Today we released v1.0.
Crow is a simple and easy to use C++ web application framework. We picked it up as an abandoned project about a year and a half ago and have been fixing, optimizing, and adding many features.
Crow is header-only, comes under BSD 3-Clause licence, uses C++11/C++14 and is pretty fast (see benchmarks) and easy to use (it is similar to Python’s Flask).
Several redditors in the thread used Crow before and were very glad to see it revived.
Injected class names
Raymond Chen writes:
C++ has a feature called injected class names, which lets you refer to the class being defined by its plain name without needing to fully qualify it with namespaces and template parameters. You have probably been taking advantage of this feature without even realizing it.
1template<typename T>
2struct Wrapper
3{
4 // using Wrapper = Wrapper<T>; <-- compiler-injected class name
5 Wrapper() { /* constructor */ }
6};
Base class names are also injected, unless they are inherited privately.
From cppreference:
Constructors do not have names, but the injected-class-name of the enclosing class is considered to name a constructor in constructor declarations and definitions.
In the Reddit thread, STL says that:
The injected-class-name can be used as a template-name or a type-name.
So both Wrapper<T>
and Wrapper
are valid in the code snippet above.
NVIDIA is building a quantum computing C++ compiler
Bryce Lelbach tweets:
We’re building a new C++ compiler for quantum computing.
He links to the article Nvidia: ‘We Are A Quantum Computing Company’. From the article:
At Nvidia’s GTC Spring event this week, the company announced that it is developing a new quantum compiler called nvq++ that targets the Quantum Intermediate Representation (QIR) specification for a low-level machine language that quantum and classical computers can use to talk to each other.
Nvidia can’t even build a C++ compiler for normal computing, so I’m sure this’ll go just perfect
Someone replies:
I have similar experience working with Nvidia - their software is known as “something to avoid at all cost” at our workplace.
The thread has many other hilarious comments, like this one:
Oh man I can’t wait for Josuttis’ book on move semantics in a quantum C++ compiler….
And of course:
Genuine question, why C++ over Rust? I don’t know much about QC, or really Rust or C++ that well tbf.
C++ Show and Tell - April 2022
The C++ Show and Tell on Reddit is becoming a regular thing. Here is the April edition. These are my highlights of the thread:
- Binary black hole collisions - screenshot
- RISC-V userspace emulator library
- Seer - a new GUI GDB front-end - screenshot
- Interactive GPU CUDA raytracer
- Monocle Security video surveillance system
- Black Sun - a space exploration game with an AI text chat sidekick
- Nomenus Rex - a CLI bulk file rename utility
Library: spdlog 1.10.0
The logging library spdlog 1.10.0 is out. Major changes are:
{fmt}
version bumped to 8.1.1- Added file event handler hooks to handle after-start and before-end logging events, which allow to have ‘prologue’ and ’epilogue’ sections in the log file.
- Added UDP logging sink.
Spdlog comes under MIT licence and can be used as a header-only or a compiled library. It is available in all major package managers, works on Linux, Windows, macOS and Android, and requires C++11.
Positive vibes in the Reddit thread.
Using subscript operator with tuples
Daisy Hollman tweets:
Cute C++ trick of the day: ever wished you could index into a tuple using
operator[]
? You can do that with numeric literal operator templates!
See it on Godbolt but maybe don’t use it in production…
So what’s going on here?
- Line 5 declares
template index
that has asize_t
template parameter determining the index value. - Lines 6–13 declare a user-defined literal operator
_i
which has template parameter of typechar...
that gets the actual characters in the literal. I haven’t seen this before, it’s different from how you normally define a user literal that takes a string. Both styles are described on cppreference. - Lines 8–12 produce a return value from the user literal operator, which has the type
index
and the template parameter value determined by a lambda which is immediately invoked on line 12. - Lines 9–11 iterate through the characters in the literal and convert them to an integer using ASCII table arithmetic.
- Lines 15–21 define a custom class
index_tuple
privately derived fromstd::tuple
which adds a subscript operator template on line 20 that takes a value of typeindex
and deduces its size. It then uses the deduced size value to callstd::get<I>
to index into the tuple. - Lines 24–25 demonstrate the usage of class
index_tuple
by indexing into it using its subscript operator, passing1_i
as the index parameter.
Some interesting responses on Twitter:
- Barry Revzin says:
Don’t need the
std::string
, can just iterate over{Chars...}
by itself (gets deduced as aninitializer_list<char>
)
- Philippe Payan says:
The real magic to me is how “10_i” <…> turns into the
operator ""_i
with two char template values (?), namely “1” and “0”, each of type char obviously. How does that happen? How is “10” broken down into “1” and “0”?
Daisy Hollman replies:
Compilers are magic! But also, the easier answer is “because the standard says it has to.”
Philippe Payan follows up:
I got it. I found it in the Standard, section 12.8 “User-defined literals”, point 5. I understand this as basically: your operator is getting bytes from the source code through the non-type template list of chars. Damn!
Cool technique, I hate it.
List of C++ videos
Hacking C++ tweets:
I’ve started a new list of talks, tutorials, and other educational videos related to C++. It’s organized by topic (e.g., generic programming, C++20, best practices, modules, CMake, …)
The list indexes over 700 videos and is a great educational resource.
Viktor Zverovich (@vzverovich):
Patricia Aas (@pati_gallardo):