A small C++ meme dump

P0843 “inplace_vector (f.k.a. static_vector, fixed_capacity_vector); P1144R8 §2.1.3. See “P1144 case study: Moving a fixed_capacity_vector (2019-02-22) and Quuxplusone/SG14 now has inplace_vector (2023-10-20).

std::pmr::vector either clears itself after move or not, depending on library vendor and most importantly depending on whether the destination has the same arena. Neither criterion relates to T’s own triviality. (Godbolt.) See also “A not-so-quick introduction to the C++ allocator model” (2023-06-02)

The math library for some reason has both scalbn(double, int) and scalbln(double, long int). Both functions simply add the int to the exponent of the floating-point number (scaling its real value by \(2^n\)). For C compatibility, they also come in float flavor (scalbnf, scalblnf) and long double flavor (scalbnl, scalblnl). Presumably scalblnf is useful on platforms where the number of bits in a float’s exponent field (e.g. 8) is greater than the number of bits in an int (e.g. 32).

Cppreference describes scalblnf and friends under the drippingly sarcastic heading “Common mathematical functions.”

I don’t even know which way around this meme is supposed to go. a.merge(b) does destructively modify b (in that it pilfers all its nodes over into a), so you might think a.merge(std::move(b)) correctly indicates that this had better be the last use of b. On the other hand, it reliably leaves b empty, not in some unspecified moved-from state — in fact, set::merge leaves its right-hand argument in a reliably useful state! — and so the use of std::move might be philosophically incorrect. Certainly it’s more tedious to type out. I don’t know, man.

Sometimes people ask, if you can forward-declare a class template or a function template, why can’t you also forward-declare a concept?

template<class T> int f(T t); // OK
template<class T> class Mine; // OK
template<class T> concept Fungible; // ill-formed

The answer is that a function or class is usable without its definition: the compiler can deal with i = f(42) or Mine<int> *p = nullptr without knowing anything else about f or Mine. But to “use” a concept, you need its definition.

template<class U> int g(U u) requires Fungible<U>;

Is g(42) a valid function call? We don’t know unless we know the value of Fungible<int>, which requires seeing the definition of Fungible. Forward-declaring concept Fungible is useless. Therefore it’s not allowed.

If you find yourself confused about the syntax of requires-expressions, or can’t think of how to write a concept testing for a particular property, just remember that requires-expressions are designed so that this works. (Including the sneaky behavior of Bar&& above!) Contrariwise, if you find yourself writing a lot of concepts that look like this meme, consider maybe not writing those concepts at all: They likely aren’t doing anything except to change the source location associated with your error messages.

Posted 2023-06-17