Constrain your user-defined conversions

Sometimes you want to add an implicit conversion to a type. This can be done by adding an implicit conversion operator. For example, std::string is implicitly convertible to std::string_view:

class string { // template omitted for simplicity
public:
    operator std::string_view() const noexcept
    {
       return std::string_view(c_str(), size());
    }
};

The conversion is safe, cheap, and std::string and std::string_view represent the same platonic value — we match Tony van Eerd’s criteria for implicit conversions and using implicit conversions is justified.

However, even when all criteria are fulfilled, the conversion can still be dangerous.

» read at think-cell »
Jonathan

Trip report: Summer ISO C++ Meeting in Varna, Bulgaria

Last week, I attended the summer 2023 meeting of the ISO C++ standardization committee in Varna, Bulgaria. This was my first meeting since the pandemic and the first meeting as official member thanks to think-cell’s participation in the German national body. In total, 18 different countries sent representatives and over 180 C++ experts attended, although some of them only remotely.

» read at think-cell »
Jonathan

Technique: Proof types to ensure preconditions

Consider a library using hidden global state that needs to be initialized by calling an initialization function. If you don’t call the function before you start using the library, it crashes.

How do you design the library in such a way that it is impossible to use it before initialization?

One idea is to use a technique where you create a special proof type, which needs to be passed as an additional parameter. Let’s look at it in more detail.

» read more »
Jonathan

New integer types I’d like to see

(Most) C++ implementations provide at least 8, 16, 32, and 64-bit signed and unsigned integer types. There are annoying implicit conversions, discussions about undefined behavior on overflow (some think it’s too much UB, others think it’s not enough), but for the most part they do the job well. Newer languages like Rust copied that design, but fixed the conversions and overflow behavior.

Still, I think there is room for innovation here. Let me talk about three new families of integer types I’d like to see.

» read more »
Jonathan

malloc() and free() are a bad API

If you need to allocate dynamic memory in C, you use malloc() and free(). The API is very old, and while you might want to switch to a different implementation, be it jemalloc, tcmalloc, or mimalloc, they mostly copy the interface. It makes sense that they do that – they want to be a mostly drop-in replacement, but it’s still unfortunate because malloc() and free() are a bad API for memory allocation.

Let’s talk why.

» read more »
Jonathan