ISO C++ June 2023 meeting "trip" report (core language)
The C++ committee had its third hybrid meeting in Varna, Bulgaria this month, to begin work on C++26. This was the first time in this location, after the original plan to host the June 2020 meeting was cancelled. From Red Hat, Jonathan Wakely was there in person, while I attended virtually, from seven time zones behind. As usual, I spent most of my time in the Core working group.
New C++26 features
We moved a few new language features at the meeting:
P2738, constexpr cast from void*
Enabling type erasure patterns without virtual functions in constant evaluation, e.g.
class Doer {
private:
const void *ob;
int (*fn)(const void *);
public:
template <typename T>
constexpr Doer(const T &t)
: ob{&t},
fn{[](const void *p) { return static_cast(p)->doit(); }}
{}
constexpr int operator()() const { return fn(ob); }
};
struct Thing { constexpr int doit() const { return 42; }; };
static_assert (Doer(Thing())() == 42);
I've already implemented this proposal for GCC 14; it was pretty trivial with the existing constexpr code.
P2741, user-generated static_assert messages
Allowing static_assert
messages that aren't string literals, e.g.
constexpr std::string_view str = "Hello";
static_assert(false, str);
P2169, placeholder variables with no name
Removing the need to come up with distinct names for variables that only need names to satisfy syntax, e.g.
int [a, _, b] = f();
RAIIType _; // ok, another variable named _
foo(_); // error, ambiguous
P2641, checking if a union member is active
This was a library motion, but requires compiler support. In constant evaluation, it's useful to be able to ask the compiler whether a particular union member is active. The paper proposes a more general mechanism, std::is_within_lifetime (ptr)
, which constant evaluation can answer based on knowing what value is currently stored in a particular object. For trivial types, this can already be tested in GCC with __builtin_constant_p (*ptr)
, but it's not straightforward to do this for a class type.
P2752, static storage for braced initializers (DR)
This isn't a new feature, but a clarification that it is OK for a compiler to put a constant initializer-list backing array into static storage even if it can't be sure that its lifetime doesn't overlap with the same one in a recursive call:
void f(std::initializer_list<int>);
void g() {
f({1,2,3}); // the array of 3 ints can now go in .rodata regardless of the definition of f
}
This standardizes an optimization I already implemented for GCC 14.
Potential C++26 features
CWG also discussed various papers that weren't ready for a vote at this meeting, including:
P1061, Structured Bindings can introduce a pack
template <class F, class Tuple>
constexpr decltype(auto) apply(F &&f, Tuple &&t)
{
auto&& [...elems] = t; // elems is a structured binding pack
return std::invoke(std::forward<F>(f),
forward_like<Tuple, decltype(elems)>(elems)...);
}
We saw this paper at the last meeting as well. At this meeting we were working to nail down the specific consequences of allowing this to be used outside of a template, as a use of the name of a structured binding pack in the pattern of a pack expansion is necessarily a dependent name. More work is needed on this.
P2662, Pack indexing
For getting at an element of a pack without writing another template.
template<class ...T>
int f( T...[0], std::tuple<T...> );
P2795, Erroneous behaviour for uninitialized reads.
The C++ committee is concerned about safety issues with buggy code in general, and working to limit the impact. This paper wants to address vulnerabilities from variables that are read without being first initialized (CWE-457). It proposes that reading such a variable no longer be undefined behavior, but rather a new category of "erroneous" behavior, which is well-defined but diagnosable: reading an erroneous value can still be rejected by something like valgrind, but it won't give you the value that happened to be at that location before. The GCC -ftrivial-auto-var-init
flag implements something similar. Various people on the committee pointed out that sometimes leaving a variable actually uninitialized is important to performance, so there needs to be a way to opt out of the new semantics; discussion of that mechanism is ongoing.
And then, of course, we spent a good amount of time resolving more subtle issues.
The C++26 process is off to a strong start; the next meeting will be in November, back in Kona.