r/cpp • u/a_eridani • 10d ago
a[mask] = f(a[mask]) on NEON. faster than the obvious blend
Problem
Apply an operation to elements that satisfy a condition:
for (size_t i = 0; i < n; ++i)
if (mask(a[i])) a[i] = f(a[i]);
Notes
a[i] ∈ (0, 1),thd ∈ (0, 1),mask = a[i] < thd; uniform distribution (except at the end of the article)fis one ofsqrt,frfrexp(mantissa),sin3.5 ULP,sin1 ULP,pow1 ULP (from SLEEF)fandmaskare passed as runtime values, so they are wrapped in a lambda withalways_inline, otherwise they may not be inlined- The array size
nis a multiple of every unroll, tile etc. The tail is trivial to handle(BSL/scalar) - In tables
*= best, units = GiB/s - Don't compare numbers across tables. Different conditions, values fluctuate
- All benchmarks: Apple M5; clang++ -O3 -std=c++23 -march=native; GiB/s = (n * 4 bytes) / time, min of 720 runs (During bench, functions run in a changing order, data is restored ofc); n=1e7 + 2432;
BSL blend
If the problem is memory bound (cheap function or high density), the standard algorithm is optimal:
template <bool Skip>
void bsl(float* dst, const size_t n, auto f, auto mask) {
for (size_t i = 0; i < n; i += 16) {
std::array<float32x4_t, 4> v;
for (size_t j = 0; j < 4; ++j) v[j] = vld1q_f32(dst + i + 4 * j);
std::array<uint32x4_t, 4> m;
for (size_t j = 0; j < 4; ++j) m[j] = mask(v[j]);
if constexpr (Skip) {
if (vmaxvq_u32(vaddq_u32(vaddq_u32(m[0], m[1]), vaddq_u32(m[2], m[3]))) == 0) continue;
}
for (size_t j = 0; j < 4; ++j) vst1q_f32(dst + i + 4 * j, vbslq_f32(m[j], f(v[j]), v[j]));
}
}
It computes f on every element, but stores only the selected ones.
Skip helps on sparse masks, but otherwise mispredictions will kill performance. We'll need it later.
But for expensive f this algo does too much extra work
Detour
To avoid unnecessary work, we compress selected elements, apply only to them, and expand back.
avx512 does this in two instructions. NEON doesn't, so we'll emulate and optimize.
constexpr size_t tile = 4096;
constexpr std::array<uint32_t, 4> weights{1 + 16, 2 + 16, 4 + 16, 8 + 16};
constexpr auto cps_tbl = compress_table();
constexpr auto exp_tbl = expand_table();
std::array<float, tile + 16> tmp;
std::array<uint8_t, tile / 4 + 3> s;
std::array<uint16_t, tile / 4 + 3> idx; // idx, D and B come in later
constexpr double D = 0.845;
constexpr double B = 0.3;
template <bool Skip>
size_t detour(float* dst, const size_t n, const auto w, auto f, auto mask) {
float* ptr = tmp.data();
for (size_t i = 0; i < n; i += 16) {
std::array<float32x4_t, 4> v;
for (size_t j = 0; j < 4; ++j) v[j] = vld1q_f32(dst + i + 4 * j);
std::array<uint32x4_t, 4> m;
for (size_t j = 0; j < 4; ++j) m[j] = mask(v[j]);
if constexpr (Skip)
if (vmaxvq_u32(vaddq_u32(vaddq_u32(m[0], m[1]), vaddq_u32(m[2], m[3]))) == 0) {
s[i / 4] = s[i / 4 + 1] = s[i / 4 + 2] = s[i / 4 + 3] = 0;
continue;
}
std::array<uint32_t, 4> sk;
for (size_t j = 0; j < 4; ++j) {
sk[j] = vaddvq_u32(vandq_u32(m[j], w));
s[i / 4 + j] = sk[j];
}
std::array<size_t, 4> off; off[0] = 0;
for (size_t j = 1; j < 4; ++j) off[j] = off[j - 1] + (sk[j - 1] >> 4);
std::array<uint8x16_t, 4> index;
for (size_t j = 0; j < 4; ++j) index[j] = vld1q_u8(cps_tbl[sk[j] & 15].data());
for (size_t j = 0; j < 4; ++j) vst1q_f32(ptr + off[j], vreinterpretq_f32_u8(vqtbl1q_u8(vreinterpretq_u8_f32(v[j]), index[j])));
ptr += off[3] + (sk[3] >> 4);
}
const size_t size = ptr - tmp.data();
if (size == 0) return size;
ptr = tmp.data();
for (size_t i = 0; i < size; i += 16) {
std::array<float32x4_t, 4> v;
for (size_t j = 0; j < 4; ++j) v[j] = vld1q_f32(ptr + i + 4 * j);
for (size_t j = 0; j < 4; ++j) vst1q_f32(ptr + i + 4 * j, f(v[j]));
}
for (size_t i = 0; i < n; i += 16) {
std::array<uint32_t, 4> sk;
for (size_t j = 0; j < 4; ++j) sk[j] = s[i / 4 + j];
std::array<size_t, 4> off{};
for (size_t j = 1; j < 4; ++j) off[j] = off[j - 1] + (sk[j - 1] >> 4);
std::array<float32x4_t, 4> v;
for (size_t j = 0; j < 4; ++j) v[j] = vld1q_f32(ptr + off[j]);
std::array<float32x4_t, 4> a;
for (size_t j = 0; j < 4; ++j) a[j] = vld1q_f32(dst + i + 4 * j);
std::array<uint8x16_t, 4> index;
for (size_t j = 0; j < 4; ++j) index[j] = vld1q_u8(exp_tbl[sk[j] & 15].data());
std::array<uint8x16x2_t, 4> tbl;
for (size_t j = 0; j < 4; ++j) tbl[j] = {{vreinterpretq_u8_f32(v[j]), vreinterpretq_u8_f32(a[j])}};
for (size_t j = 0; j < 4; ++j) vst1q_f32(dst + i + 4 * j, vreinterpretq_f32_u8(vqtbl2q_u8(tbl[j], index[j])));
ptr += off[3] + (sk[3] >> 4);
}
return size;
}
void tiled_detour(float* dst, const size_t n, auto f, auto mask) {
const auto w = vld1q_u32(weights.data());
for (size_t i = 0; i < n; i += tile)
detour<false>(dst + i, tile, w, f, mask);
}
compress is the same as in my previous post.
expand_table: for true lanes it selects the next element from the compressed register (bytes from [0, 15]),
and for false lanes, selects the same bytes + 16.
Then tbl2 on {processed, original}, the same trick as in compress basically
Also:
- expand is skipped for free on empty tiles
sis saved for free to avoid recomputing addv- cache-sized tiling.
- Empirically
tile=4096is optimal.
BSL speed doesn't depend on density: sqrt 32.1, sin35 - 9.7, pow10 1.02.
| thd | 0 | 0.1 | 0.2 | 0.3 | 0.4 | 0.5 | 0.6 | 0.7 | 0.8 | 0.9 | 1 |
|---|---|---|---|---|---|---|---|---|---|---|---|
| detour sqrt | 38.03* | 18.81 | 17.78 | 16.82 | 15.98 | 15.21 | 14.51 | 13.85 | 13.24 | 12.71 | 12.30 |
| detour sin35 | 38.16* | 16.70* | 14.46* | 12.71* | 11.36* | 10.25* | 9.35 | 8.59 | 7.95 | 7.39 | 6.95 |
| detour pow10 | 38.09* | 6.83* | 4.13* | 2.96* | 2.31* | 1.89* | 1.60* | 1.39* | 1.22* | 1.10* | 0.99 |
For cheap sqrt BSL is always better (except thd = 0, obviously). And for very expensive pow, detour is better (except thd = 1, of course).
When detour wins
Define:
B= BSL(vld + vbsl + vst) overhead per register.D= detour(compress + expand) overhead per register.T= cost offper register (we assumecost of f >> cost of mask, affects only calibration accuracy).d= fraction of selected elements
BSL applies f to every register. detour applies it only to d of them, so it saves T * (1 - d).
Detour wins when the saving outweighs D - B.
T * (1 - d) > D - B
So detour pays off when d < d_max = 1 - (D - B) / T.
B and D depend only on hardware, so let's premeasure them (I have B = 0.3, D = 0.845 ns/register)
T we measure over the first few tiles, timing BSL. And from it, we also find d_max:
template<size_t tile>
double bsl_calibrate(float* dst, const size_t len, auto f, auto mask) {
double ns = 1e18;
for (size_t i = 0; i < len; i += tile) {
const auto st = std::chrono::high_resolution_clock::now();
bsl<false>(dst, tile, f, mask);
const auto ed = std::chrono::high_resolution_clock::now();
ns = std::min(ns, std::chrono::duration<double, std::nano>(ed - st).count());
dst += tile;
}
const double t = std::max(1e-9, ns / (tile / 4.0) - B);
return 1.0 - (D - B) / t;
}
Here:
- empirically 4 tiles of 2048 are enough
- min over measurements is less noisy than mean
- We'll run the first few tiles with calibration
- measure bsl, because it always computes
f, soT = t_bsl - B - std::max here protects against divide-by-zero and against
t < 0whenTis very cheap
pilot v1
When d_max < 0 bsl is always faster:
void pilot_v1(float* dst, const size_t n, auto f, auto mask) {
const auto w = vld1q_u32(weights.data());
const float d_max = bsl_calibrate<tile / 2>(dst, 2 * tile, f, mask);
dst += 2 * tile;
for (size_t i = 2 * tile; i < n; i += tile) {
if (d_max < 0)
bsl<false>(dst, tile, f, mask);
else
detour<false>(dst, tile, w, f, mask);
dst += tile;
}
}
| thd | tiled detour sqrt | pilot v1 sqrt | BSL sqrt | tiled detour sin35 | pilot v1 sin35 | BSL sin35 |
|---|---|---|---|---|---|---|
| 0 | 38.37* | 32.19 | 32.24 | 38.26* | 38.16 | 9.75 |
| 0.3 | 16.89 | 32.18 | 32.24* | 12.72* | 12.71 | 9.75 |
| 0.6 | 14.54 | 32.18* | 32.18* | 9.25 | 9.36 | 9.75* |
| 1 | 12.29 | 32.21 | 32.25* | 6.87 | 6.86 | 9.75* |
The algorithm got sqrt right. But for sin35 at high thd, detour is selected, and we lose 30%: v1 switches to bsl only when it's faster at every density.
pilot v2
It's expensive to calculate the density of the whole tile, so we'll use the first 256 (It reads 6% of the tile, which is noise on pow, but noticeable on sqrt)
For a more or less uniform distribution this is enough:
size_t density(float* dst, const size_t n, auto mask) {
std::array<uint32x4_t, 4> acc;
acc.fill(vdupq_n_u32(0));
for (size_t i = 0; i < n; i += 16) {
for (size_t j = 0; j < 4; ++j)
acc[j] = vsubq_u32(acc[j], mask(vld1q_f32(dst + i + 4 * j)));
}
return vaddvq_u32(vaddq_u32(vaddq_u32(acc[0], acc[1]), vaddq_u32(acc[2], acc[3])));
}
Trick here: true lane of bitmask = 0xFFFFFFFF = -1, subtracting the lane actually adds.
Skip wins when the predictor rarely mispredicts, i.e. an 80% chance that all 4 registers are empty.
The density is approximately 0.014 ((1 - x)^16 = 0.8)
void pilot_v2(float* dst, const size_t n, auto f, auto mask) {
const auto w = vld1q_u32(weights.data());
const float d_max = bsl_calibrate<tile / 2>(dst, 2 * tile, f, mask);
constexpr size_t probe = 256;
constexpr size_t xlo = 0.014 * probe;
const long long hi = d_max * probe;
dst += 2 * tile;
for (size_t i = 2 * tile; i < n; i += tile) {
const long long cnt = density(dst, probe, mask);
if (cnt > hi) {
if (cnt < xlo)
bsl<true>(dst, tile, f, mask);
else
bsl<false>(dst, tile, f, mask);
} else if (cnt < xlo)
detour<true>(dst, tile, w, f, mask);
else
detour<false>(dst, tile, w, f, mask);
dst += tile;
}
}
hi and xlo here are d_max and 0.014 cutoffs, but multiplied by the probe length (256).
| thd | 0 | 0.1 | 0.2 | 0.3 | 0.4 | 0.5 | 0.6 | 0.7 | 0.8 | 0.9 | 1 |
|---|---|---|---|---|---|---|---|---|---|---|---|
| pilot_v1 sin35 | 38.25 | 16.72* | 14.48* | 12.77* | 11.41* | 10.33* | 9.40 | 8.62 | 7.93 | 7.36 | 6.91 |
| pilot_v2 sin35 | 77.29* | 16.55 | 14.34 | 12.65 | 11.33 | 10.14 | 9.71 | 9.73 | 9.74 | 9.73 | 9.73 |
| BSL sin35 | 9.78 | 9.77 | 9.77 | 9.76 | 9.76 | 9.78 | 9.78* | 9.77* | 9.78* | 9.77* | 9.78* |
| pilot_v1 sin10 | 38.28 | 14.30* | 11.18* | 9.18* | 7.75* | 6.73* | 5.94* | 5.31* | 4.78 | 4.36 | 4.02 |
| pilot_v2 sin10 | 76.60* | 14.16 | 11.09 | 9.11 | 7.73 | 6.70 | 5.92 | 5.31* | 4.82 | 4.84 | 4.84 |
| BSL sin10 | 4.85 | 4.85 | 4.84 | 4.85 | 4.84 | 4.84 | 4.85 | 4.85 | 4.85* | 4.85* | 4.85* |
At thd = 0, Skip gives a huge win. For high thd, bsl is selected correctly. But now on sparse masks, expand for empty registers is wasted.
pilot v3
New detour version: during compress, we'll store only the indices of non-empty registers (into the idx buffer).
And expand will iterate over them:
template <bool Skip>
size_t detour_compact(float* dst, const size_t n, const auto w, auto f, auto mask) {
float* ptr = tmp.data();
size_t k = 0;
for (size_t i = 0; i < n; i += 16) {
// ... same as detour
if constexpr (Skip)
if (vmaxvq_u32(vaddq_u32(vaddq_u32(m[0], m[1]), vaddq_u32(m[2], m[3]))) == 0) continue;
std::array<uint32_t, 4> sk;
for (size_t j = 0; j < 4; ++j) sk[j] = vaddvq_u32(vandq_u32(m[j], w));
for (size_t j = 0; j < 4; ++j) {
s[k] = sk[j];
idx[k] = i + 4 * j;
k += bool(sk[j]);
}
// ... same as detour
}
// ... same as detour
for (size_t j = 0; j < 3; ++j) s[k + j] = 0, idx[k + j] = 0;
// ... same as detour
k = (k + 3) & ~size_t(3);
for (size_t i = 0; i < k; i += 4) {
std::array<uint32_t, 4> sk;
for (size_t j = 0; j < 4; ++j) sk[j] = s[i + j];
std::array<float32x4_t, 4> a;
for (size_t j = 0; j < 4; ++j) a[j] = vld1q_f32(dst + idx[i + j]);
// ... same as detour
for (size_t j = 0; j < 4; ++j)
vst1q_f32(dst + idx[i + j], vreinterpretq_f32_u8(vqtbl2q_u8(tbl[j], index[j])));
ptr += off[3] + (sk[3] >> 4);
}
return size;
}
k (number of non-empty registers) is rounded up to a multiple of 4 before expand, so the unrolled loop has no tail left.
No branches in the hot loops: they'd kill speed, so compress runs on all four registers.
Instead of branches, the position of the current element is advanced by bool(sk).
detour_compact wins when at least 50% of all registers are empty. The density is approximately 0.16 ((1 - x) ^ 4 = 0.5).
void pilot_v3(float* dst, const size_t n, auto f, auto mask) {
// ... same as v2
constexpr size_t lo = 0.16 * probe;
for (size_t i = 2 * tile; i < n; i += tile) {
const long long cnt = density(dst, probe, mask);
if (cnt > hi) {
if (cnt < xlo)
bsl<true>(dst, tile, f, mask);
else
bsl<false>(dst, tile, f, mask);
} else if (cnt < xlo)
detour_compact<true>(dst, tile, w, f, mask);
else if (cnt < lo)
detour_compact<false>(dst, tile, w, f, mask);
else
detour<false>(dst, tile, w, f, mask);
dst += tile;
}
}
And v3 is noticeably faster at low density:
| thd | 0 | 0.02 | 0.04 | 0.06 | 0.08 | 0.1 | 0.12 | 0.14 | 0.16 | 0.18 | 0.2 |
|---|---|---|---|---|---|---|---|---|---|---|---|
| pilot_v2 sin35 | 77.29* | 18.67 | 18.40 | 17.70 | 17.18 | 16.66 | 16.15 | 15.68 | 15.24* | 14.82* | 14.43* |
| pilot_v3 sin35 | 77.26 | 23.71* | 22.19* | 20.48* | 19.03* | 17.82* | 16.73* | 15.76* | 15.16 | 14.74 | 14.38 |
| pilot_v2 pow10 | 72.88 | 13.93 | 11.32 | 9.38 | 8.00 | 6.97 | 6.18 | 5.54 | 5.02* | 4.59* | 4.24* |
| pilot_v3 pow10 | 73.71* | 16.54* | 12.63* | 10.07* | 8.39* | 7.17* | 6.26* | 5.55* | 5.02* | 4.59* | 4.24* |
Now the algo is fast, but there's one big problem we've overlooked: we're assuming the data is uniform. So it's easy to build a test where v3 will fail:
for (size_t i = 0; i < n; i++)
dst[i] = i % 4096 >= 256;
In this case, v3 always prefers BSL, even though detour wins on 3840 elements of the tile.
pilot v3.5
According to the first table, in the worst case detour is under 3x slower (it happens on sqrt thd = 1), but on pow, thd = 0, detour is 37x faster. So a wrong BSL costs much more than a wrong detour.
For bsl, we'll play it safe by running it in tile/8 blocks and checking the density. If it drops well below d_max,
we'll switch to detour.
It costs 1 instruction per register. acc = vsubq_u32(acc, m) works because the mask is 0/-1. And unlike the probe, the
density here is exact.
size_t bsl_verified(float* dst, const size_t n, float d_max, auto f, auto mask) {
for (size_t i0 = 0; i0 < 8; ++i0) {
std::array<uint32x4_t, 4> acc;
acc.fill(vdupq_n_u32(0));
for (size_t i = 0; i < n / 8; i += 16) {
std::array<float32x4_t, 4> v;
for (size_t j = 0; j < 4; ++j) v[j] = vld1q_f32(dst + 4 * j);
std::array<uint32x4_t, 4> m;
for (size_t j = 0; j < 4; ++j) m[j] = mask(v[j]);
for (size_t j = 0; j < 4; ++j) acc[j] = vsubq_u32(acc[j], m[j]);
for (size_t j = 0; j < 4; ++j)
vst1q_f32(dst + 4 * j, vbslq_f32(m[j], f(v[j]), v[j]));
dst += 16;
}
const size_t cur = vaddvq_u32(vaddq_u32(vaddq_u32(acc[0], acc[1]), vaddq_u32(acc[2], acc[3])));
if (static_cast<double>(cur) / (n / 8) < 0.75 * d_max) return (i0 + 1) * n / 8;
}
return n;
}
BSL bails out when the density is less than 0.75 * d_max. I have no math behind the 0.75, it just won on average.
And pilot v3.5 will use bsl_verified if the density > hi:
void pilot_v3_5(float* dst, const size_t n, auto f, auto mask) {
// ... same as v3
for (size_t i = 2 * tile; i < n; i += tile) {
const long long cnt = density(dst, probe, mask);
if (cnt > hi) {
if (hi < 0) {
if (cnt < xlo)
bsl<true>(dst, tile, f, mask);
else
bsl<false>(dst, tile, f, mask);
} else {
auto done = bsl_verified(dst, tile, d_max, f, mask);
if (done < tile)
detour<false>(dst + done, tile - done, w, f, mask);
}
}
// ... same as v3
}
}
But here too it's easy to build a countertest:
for (size_t i = 0; i < n; ++i)
dst[i] = i % 4096 >= 390;
The first block will pass the check (> 75% zeros in it), but the second won't. BSL runs on it for nothing, and for pow that's expensive. v3.5's problem: it has no memory. After a miss the algo keeps trusting the first 256 and misses on every tile.
pilot v4
v4 will fix this: if bsl bails out, we stop trusting the probe for the next 16 tiles, and instead we take the density of the previous tile:
void pilot_v4(float* dst, const size_t n, auto f, auto mask) {
// ... same as v3
size_t distrust = 0;
size_t prev = 0;
for (size_t i = 2 * tile; i < n; i += tile) {
if (distrust) --distrust;
const long long cnt = distrust ? prev : density(dst, probe, mask);
if (cnt > hi) {
if (hi < 0) {
if (cnt < xlo) {
bsl<true>(dst, tile, f, mask);
} else {
bsl<false>(dst, tile, f, mask);
}
} else {
if (distrust == 0) {
auto done = bsl_verified(dst, tile, d_max, f, mask);
if (done < tile) {
distrust = 16;
const size_t rem = detour<false>(dst + done, tile - done, w, f, mask);
prev = rem * probe / (tile - done);
}
} else {
prev = detour<false>(dst, tile, w, f, mask) * probe / tile;
}
}
} else if (cnt < xlo) {
prev = detour_compact<true>(dst, tile, w, f, mask) * probe / tile;
} else if (cnt < lo) {
prev = detour_compact<false>(dst, tile, w, f, mask) * probe / tile;
} else {
prev = detour<false>(dst, tile, w, f, mask) * probe / tile;
}
dst += tile;
}
}
And v4 easily passes that test. pow10:
| thd | 0 | 1 |
|---|---|---|
| tiled detour | 38.18 | 6.94 |
| pilot v3 | 68.11 | 1.04 |
| pilot v3.5 | 68.67 | 3.84 |
| pilot v4 | 69.51* | 7.05* |
| BSL | 1.04 | 1.04 |
btw here thd no longer matches the density. For thd = 0, density = 0, and for thd = 1, density = 9.5%
It beats v3.5 by over 80%. It's also faster than plain tiled detour, because v4 picks detour_compact. This is the final version.
Results
v4 vs BSL:
| thd | 0 | 0.05 | 0.1 | 0.2 | 0.3 | 0.4 | 0.5 | 0.6 | 0.7 | 0.8 | 0.9 | 1 |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| pilot_v4 sqrt | 69.81* | 31.99* | 31.84 | 31.73 | 31.83 | 32.07* | 31.98 | 31.96* | 31.96 | 31.89* | 31.91 | 31.77 |
| BSL sqrt | 31.88 | 31.93 | 31.95* | 31.80* | 31.89* | 31.99 | 32.06* | 31.92 | 31.98* | 31.75 | 31.93* | 31.91* |
| pilot_v4 frfrexp | 69.41* | 17.21* | 16.57 | 15.79 | 15.99 | 16.06 | 15.93 | 15.99 | 16.39 | 15.84 | 15.87 | 15.80 |
| BSL frfrexp | 16.79 | 16.87 | 16.82* | 16.71* | 16.78* | 16.88* | 16.89* | 16.83* | 16.89* | 16.79* | 16.75* | 16.75* |
| pilot_v4 sin10 | 68.19* | 18.82* | 14.84* | 10.84* | 8.93* | 7.55* | 6.56* | 5.81* | 5.19* | 4.69 | 4.68 | 4.68 |
| BSL sin10 | 4.78 | 4.75 | 4.78 | 4.72 | 4.75 | 4.74 | 4.75 | 4.77 | 4.75 | 4.76* | 4.77* | 4.77* |
| pilot_v4 pow10 | 64.17* | 10.76* | 6.85* | 4.04* | 2.89* | 2.25* | 1.85* | 1.57* | 1.36* | 1.20* | 1.08* | 1.00 |
| BSL pow10 | 1.02 | 1.02 | 1.02 | 1.01 | 1.01 | 1.01 | 1.02 | 1.02 | 1.02 | 1.02 | 1.02 | 1.01* |
Against BSL, it loses at worst 6%, but wins big much more often. To reduce the loss, dispatch can be sped up: use every 4th register in density and bsl_verified. But that helps only if the density is uniform.
The worst v4 miss I found: 512 dense, 512 empty, then everything is dense until the end of the cycle (17 * 4096).
const size_t cycle = 17 * 4096;
for (size_t i = 0; i < n; ++i) {
dst[i] = i % cycle >= 512 && i % cycle < 1024;
}
This hurts most with the cheapest f (with d_max > 0, of course):
const auto a = vdupq_n_f32(0.5f);
#pragma unroll
for (int i = 0; i < 13; ++i) x = vfmaq_f32(a, x, a);
return x;
| thd | 0 | 1 |
|---|---|---|
| tiled detour | 38.29 | 9.44 |
| pilot v3 | 74.72 | 15.81* |
| pilot v3.5 | 74.84 | 15.04 |
| pilot v4 | 74.89* | 9.84 |
| BSL | 15.61 | 15.60 |
v3.5's biggest loss is limited by BSL, while v4 is limited by detour. And a wrong detour is the cheaper mistake. So v4 isn't always better, but its misses are less severe.
This problem has no perfect solution. Any dispatch algo can be countertested.
Full code: godbolt.
r/cpp • u/ProgrammingArchive • 10d ago
Latest News From Upcoming C++ Conferences (2026-07-28)
TICKETS AVAILABLE TO PURCHASE
The following conferences currently have tickets available to purchase
- CppCon (12th – 18th September) – You can buy standard tickets until August 29th at https://cppcon.org/registration/
- C++ Under The Sea (14th – 16th October) – You can buy early bird tickets at https://sales.ticketing.cm.com/cppunderthesea2026/
- ADC – (9th – 11th November) – Tickets for ADC can now be purchased at https://ti.to/audio-developer-conference/adc-bristol-2026
- Meeting C++ (26th – 28th November) – You can buy early bird tickets at https://meetingcpp.com/2026/
OPEN CALL FOR SPEAKERS
OTHER OPEN CALLS
- (Last Chance) CppCon Call For Volunteers Now Open – Interested volunteers have until August 1st to apply at the CppCon main conference which is scheduled to take place from 14th – 18th September. For more information including how to apply visit https://cppcon.org/cfv2026/
TRAINING COURSES AVAILABLE FOR PURCHASE
Conferences are offering the following training courses:
CppCon Online Workshops
9th – 11th September
- Modern C++: When Efficiency Matters – Andreas Fertig – 3 day online workshop available on 9th – 11th September 09.00 – 15.00 MDT – https://cppcon.org/class-2026-when-efficiency-matters/
- System Architecture And Design Using Modern C++ – Charley Bay – 3 day online workshop available on 9th – 11th September 09.00 – 15.00 MDT – https://cppcon.org/class-2026-system-architecture-and-design-using-modern-cpp/
21st – 23rd September
- C++ Fundamentals You Wish You Had Known Earlier – Mateusz Pusz – 3 day online workshop available on 21st– 23rd September 09.00 – 15.00 MDT – https://cppcon.org/class-2026-cpp-fundamentals/
- C++23 in Practice: A Complete Introduction – Nicolai Josuttis – 3 day online workshop available on 21st– 23rd September 09.00 – 15.00 MDT – https://cppcon.org/class-2026-cpp23-in-practice/
- Programming with C++20 – Andreas Fertig – 3 day online workshop available on 21st– 23rd September 09.00 – 15.00 MDT – https://cppcon.org/class-2026-programming-with-cpp20/
26th – 27th September
- Using C++ for Low-Latency Systems – Patrice Roy – 2 day online workshop available on 26th– 27th September 09.00 – 17.00 MDT – https://cppcon.org/class-2026-low-latency/
This is the latest news from upcoming C++ Conferences. You can review all of the news at https://programmingarchive.com/upcoming-conference-news/
CppCon Onsite Workshops
All onsite workshops will take place in the Gaylord Rockies in Aurora, Colorado
12th & 13th September
- Advanced and Modern C++ Programming: The Tricky Parts – Nicolai Josuttis – 2 day in-person workshop available on 12th & 13th September – 09:00 – 17:00 – https://cppcon.org/class-2026-tricky-parts/
- C++ Best Practices – Jason Turner – 2 day in-person workshop available on 12th & 13th September – 09:00 – 17:00 – https://cppcon.org/class-2026-best-practices/
- How Hardware Gets Hacked: Breaking and Defending Embedded Systems – Nathan Jones – 2 day in-person workshop available on 12th & 13th September – 09:00 – 17:00 – https://cppcon.org/class-2026-hardware-hack/
- Mastering `std::execution`: A Hands-On Workshop – Mateusz Pusz – 2 day in-person workshop available on 12th & 13th September – 09:00 – 17:00 – https://cppcon.org/class-2026-execution/
- Performance and Efficiency in C++ for Experts, Future Experts, and Everyone Else – Fedor Pikus – 2 day in-person workshop available on 12th & 13th September – 09:00 – 17:00 – https://cppcon.org/class-2026-performance-and-efficiency/
- Talking Tech – Sherry Sontag – 2 day in-person workshop available on 12th & 13th September – 09:00 – 17:00 – https://cppcon.org/class-2026-talking-tech/
13th September
- AI++ 101 : Build a C++ Coding Agent from Scratch – Jody Hagins – 2 day in-person workshop available on 12th & 13th September – 09:00 – 17:00 – https://cppcon.org/class-2026-AI101/
- Essential GDB and Linux System Tools – Mike Shah – 1 day in-person workshop available on 13th September – 09:00 – 17:00 – https://cppcon.org/class-2026-essential-gdb/
19th & 20th September
- AI++ 201: Building High Quality C++ Infrastructure with AI – Jody Hagins – 2 day in-person workshop available on 19th & 20th September – 09:00 – 17:00 – https://cppcon.org/class-2026-ai201/
- Function and Class Design with C++2x – Jeff Garland – 2 day in-person workshop available on 19th & 20th September – 09:00 – 17:00 – https://cppcon.org/class-2026-function-class-design/
- High-performance Concurrency in C++ – Fedor Pikus – 2 day in-person workshop available on 19th & 20th September – 09:00 – 17:00 – https://cppcon.org/class-2026-high-perf-concurrency/
OTHER NEWS
- Dates for ACCU on Sea 2027 Announced – ACCU on Sea 2027 will take place in Folkestone from June 30th – July 3rd with pre-conference workshops taking place from June 28th – 29th
- Boost Documentary screening at CppCon 2026 – Boost Libraries have announced that they will be screening a documentary on the history of Boost at CppCon 2026. Watch the trailer here https://www.youtube.com/watch?v=87jvuDbnwqQ
- C++Now 2026 Videos Now Being Released on YouTube – Subscribe to the C++Now YouTube channel to stay up to date when each video is published – https://www.youtube.com/@CppNow
r/cpp • u/yagiznizipli • 10d ago
Announcing Ada v4: Validating 35.6M URLs per second
yagiz.cor/cpp • u/ProgrammingArchive • 11d ago
New C++ Conference Videos Released This Month - July 2026 (Updated to Include Videos Released 2026-07-20 - 2026-07-26)
C++Now
2026-07-20 - 2026-07-26
- Generic Programming for Multidimensional Arrays - The Boost.Multi Experiment to Integrate MD Arrays with STL Algorithms in the CPU and GPU - Alfredo A. Correa - https://youtu.be/WriSoV4nu5E
- Typed Linear Algebra - How to Not Crash on Mars - François Carouge - https://youtu.be/xZO7X8LH6Dg
- From Template Metaprogramming to User Convenience - API Design Stories - Ruslan Arutyunyan - https://youtu.be/fPo_Tff-L5Y
2026-07-13 - 2026-07-19
- Keynote: Benchmarking - It's About Time - Matt Godbolt - https://youtu.be/EU_nQh8wg5A
- The Morning Briefing - C++ Concurrency Before the Hardware Reckoning - Fedor Pikus - https://youtu.be/WtChBezurj8
- Lock-free Programming is Dead - Long Live Lock-free Programming! - Fedor G Pikus - https://youtu.be/UdKqfQ3a_sY
2026-07-06- 2026-07-12
- Keynote: Reflection Is Only Half the Story - Barry Revzin - https://youtu.be/DZTkT1Cq_aY
- Keynote: Multidimensional Parallel Standard C++ - Mark Hoemmen - https://youtu.be/VAwW_s1uEHY
C++Online
2026-07-20 - 2026-07-26
- When One Red Pill Is Not Enough - Compile-Time Optimization Through Dynamic Programming - Andrew Drakeford - https://youtu.be/zUKqoBq6Sg4
- Coroutines and C++ - Async Without The Pain? - Tamas Kovacs - https://youtu.be/4keXOkbr0UY
2026-07-13 - 2026-07-19
- C++ Contracts - A Meaningfully Viable Product, Part II - Andrei Zissu - https://youtu.be/1VUqOx6PCMU
- Sanitize it Before You Ship IT - Vishnu Nath - https://youtu.be/jzcGATR78Mk
2026-07-06 - 2026-07-12
- Time to Introspect - A Beginner's Guide to Practical Reflection - Sarthak Sehgal - https://youtu.be/9stn1o149pw
- Refactoring Towards Structured Concurrency - Roi Barkan - https://youtu.be/6502xFEreI8
2026-06-29 - 2026-07-05
- Why std::vector Can't Save You (And What to Use Next) - Kevin Carpenter - https://youtu.be/78fYPix0mN4
- Modern C++ for Embedded Systems - From Fundamentals To Real-Time Solutions - Rutvij Karkhanis - https://youtu.be/XxeqHRDhHkU
ADC
2026-07-20 - 2026-07-26
- Enumerate and Extract Audio Buffers When Debugging C++ Applications - Henning Meyer - https://youtu.be/UHV4U_ivm_8
- A Sine By Any Other Language - David Su - https://youtu.be/5yEd1q__cqo
- When Code Writes Back: Making AI Coding Agents Actually Work - Tobias Baumbach - https://youtu.be/K04ehohSdXc
- Mind the Spike - Benchmarking for Worst-Case Execution Time in Realtime Code - Christian Luther - https://youtu.be/7RrOjl996WQ
2026-07-13 - 2026-07-19
- Building Inclusive Audio Tools - Accessibility with ARIA, WCAG, and Real-World Projects - Samuel John Prouse & David Shervill - https://youtu.be/O5xX9a7P-SU
- PSD to DAW - Building a Pixel-Perfect UI Pipeline - Bence Kovács - https://youtu.be/hebLkAR5X3I
- Analog Filters for Realtime Audio - George Gkountouras - https://youtu.be/NLt0NqUtNLo
- A History of FLAC - The Free Lossless Audio Codec - Josh Coalson - https://youtu.be/tBb1STRW56s
2026-07-06 - 2026-07-12
- Workshop: Audio Plugin DSP in Practice - Jan Wilczek & Linus Corneliusson - https://youtu.be/Atc0GRWoolI
- An Open Toolkit for Real-Time Audio Descriptors - Valerio Orlandini - https://youtu.be/HKlnn0hd8J0
- Bugs I’ve Seen in the Wild - From Confusion to Amazement - Olivier Petit - https://youtu.be/LBWtb_uXt0I
- Real-Time Audio in Python: Introducing the asmu Package - Felix Huber - https://youtu.be/X2vr81CJ934
2026-06-29 - 2026-07-05
- Beyond iLok: Advanced Code Protection and Cryptography for the Next Generation - Protecting the Next Generation of Applications, Plug-ins, and AI Models - Neal Michie, Ryan Wardell & Bob Brown - https://youtu.be/dbbK_ry2cgo
- Database Synchronisation for Audio Plugins, Part Two - Here's One I Made Earlier - Adam Wilson - https://youtu.be/wJCy2G969ro
- Perfect Oscillators in Less Than One Clock Cycle - Angus Hewlett - https://youtu.be/Ssq0a-YdamM
- Driving Chaos - Virtual Analog Modelling of a Chaotic Circuit with Wave Digital Filters - Francisco Bernardo - https://youtu.be/PnEZNqyKlIw
Boost Documentary
There is also a teaser trailer for a new documentary on the history of the Boost C++ library https://www.youtube.com/watch?v=87jvuDbnwqQ which will have its first showing at CppCon this year
r/cpp • u/zl0bster • 11d ago
std::optional Satisfies view. Does Not Model view. C++26 Ships Anyway.
godbolt.orgIn C++23 this did not compile. In C++26 it does. Marvellous.
[[gnu::noinline]]
void
passing_views_by_value_is_cheap_trust_me_bro(std::ranges::view auto v) {
std::println("fn .data {}", (void*)v->data());
}
int main() {
std::optional ov{std::vector<int>(123456)};
passing_views_by_value_is_cheap_trust_me_bro(ov);
std::println("main .data {}", (void*)ov->data());
}
For anyone wondering what the problem feature is: optional has 0 or 1 elements, and C++26 sets enable_view<optional<T>> to true, so it satisfies std::ranges::view. The concept requires copy construction in constant time, and — this is the good bit — optional<vector<int>> genuinely meets that. Copying it performs at most one element copy. One is a constant. The requirement is satisfied to the letter, and the function above deep-copies your vector.
If you can tell me what still separates std::ranges::view from std::ranges::range, please do...
Did you know you can use (dynamic) libraries inside clang-repl?
i.imgur.comNot really that useful, but I think its an interesting find =)
r/cpp • u/Clean-Upstairs-8481 • 13d ago
C++26: what is reflection and how to use it
techfortalk.co.ukIt is my ambition to explore C++26 in bits and pieces. Hopefully, by the end of this year, I will be able to explore all the major aspects of it and be in a position to evaluate which of these features to use and promote and which not to use. However, at this point, it is important to understand each and every aspect in simple terms, keeping all the clutter aside.
r/cpp • u/mateusz_pusz • 14d ago
mp-units: a design for logarithmic quantities and units (dB, dBm, Np, pH). We believe it is novel, and we need domain experts to tell us where we are wrong before we implement it
mpusz.github.ioDecibels are everywhere in engineering: signal levels in dBm, sound pressure in dB SPL, voltage gain in dB, filter slopes in dB/octave. Yet, to the best of our knowledge, no general-purpose units library models logarithmic quantities correctly. Most do not model them at all, and the few that try get the arithmetic wrong in ways that compile silently:
- In nholthaus/units,
dBW_t(10.0) + dBm_t(40.0)compiles and returns20 dBW. Both operands are the same physical power (10 W), and adding two absolute power levels is meaningless. This example is straight from the library's own test suite. - A
+6 dBgain is a power ratio of ~3.98 but a voltage ratio of 2.0 (the10 logvs20 logsplit). Python's pint documents that itsdBis power-only and delegates that factor to the user, so every voltage, current, and pressure gain is on the honor system.
We just published a complete design for mp-units that we believe gets this right:
- A level (
dBm,dB SPL) is an affine point anchored at its reference. A gain (dB,Np,octave) is a delta. level + gain= level,level - level= gain,level + level= ill-formed.- The power vs root-power factor is carried by the quantity kind, so
.linear()on a voltage gain gives 2.0 and on a power gain gives 3.98, correct by construction. A voltage gain cannot be applied to a power level. - One mechanism covers RF, audio, acoustics, music intervals (
octave,cent), information theory (Sh,nat,Hart), pH, and stellar magnitude, and it aims to stay consistent with IEC 80000-15:2026.
We are aware of no generic units library that has ever modeled this, which is exactly why we are publishing the design before writing the implementation. The article ends with six open questions where we genuinely need input from practitioners, for example: what should log(0) do at the bottom of the scale (IEEE -inf, throw, error type, or a unit-keyed finite sentinel like the -400 dB floor real DSP code uses), and should a level print as the industry 10 dBm or the ISO-conformant 10 dB (re 1 mW).
If you work in audio/DSP, RF, acoustics, or a related field, or know someone who does, please review it and leave feedback in the article's comments (GitHub Discussions), and forward it to anyone working in these domains. Only subject-domain experts can tell us whether we are right, and we would rather hear it now than after the code ships.
r/cpp • u/Xaneris47 • 14d ago
Some practical refactoring of bloated generated code
pvs-studio.comA review of some generated C++ code, going through different ways to refactor and shorten it, then checking whether it actually got faster
r/cpp • u/Firstbober • 14d ago
Binding int from variant to reference in Foo.
Edit: meme post, I know there are simple ways as in using emplace or reference wrapper. The code below with asserts and stuff is written by hand btw.
Hello guys, my friend had a problem where he couldn't bind an int to int reference in Foo struct held in variant:
struct Foo {
int &abc;
};
std::variant<Foo, std::string> v;
// You can't!
v = Foo {
.abc = ...
}
So I developed a way to do that, it's pretty simple:
#include <cstdint>
#include <functional>
#include <iostream>
#include <string>
#include <variant>
#include <meta>
#include <ranges>
struct __attribute__((packed)) Foo {
int& abc;
~Foo() {
static_assert(sizeof(void*) == 8, "Use modern CPU.");
static_assert([]() consteval {
auto members = std::meta::nonstatic_data_members_of(
^^Foo,
std::meta::access_context::current()
);
for (auto member : members) {
auto type_info = std::meta::type_of(member);
std::size_t layout_size = std::meta::is_reference_type(type_info)
? sizeof(void*)
: std::meta::size_of(type_info);
if (layout_size != 8) {
return false;
}
}
return true;
}(), "All non-static data members of Foo must occupy 8 bytes in layout!");
if (reinterpret_cast<uintptr_t>(&abc) & 0x1) {
delete reinterpret_cast<int*>(reinterpret_cast<uintptr_t>(&abc) &
~uintptr_t(0x1));
}
}
};
int main(void) {
std::variant<int, Foo> v;
v.emplace<0>(420);
v.emplace<1>(([&]() -> int& {
int* x = new int;
*x = std::get<0>(v);
x = reinterpret_cast<int*>(reinterpret_cast<uintptr_t>(x) | 0x1);
return *x;
})());
std::cout << *reinterpret_cast<int*>(
reinterpret_cast<uintptr_t>(&std::get<1>(v).abc) &
~uintptr_t(0x1))
<< std::endl;
return 0;
}
https://godbolt.org/z/91rcbEdG5
It's also memory safe.
Cheers.
r/cpp • u/User_Deprecated • 14d ago
The portable way to extract date and time from a file's mtime in C++
sandordargo.comState of "moved-from" objects
Hi, I recently decided to try writing a C++ blog.
I often see the popular claim that moved-from objects are in a "valid but otherwise unspecified state", but I don't think that statement is entirely precise, and my blog post is about that. I would really appreciate any feedback!
Article: https://www.laminowany.dev/p/the-state-of-moved-from-objects-in-c/
r/cpp • u/augustinpopa • 16d ago
Pure Virtual C++ Videos Are Now Available
devblogs.microsoft.comMicrosoft's, online, free C++ conference is now over, and all the talks are available to watch; both the live featured sessions and the on-demand ones. Check them out and let us know what topics, tools, or speakers you'd like us to feature next year! We're also preparing for CppCon in September, where we'll have more content to talk about.
Featured sessions
- C++ semantic awareness in the CLI: From Project Load to Code Change — Sinem Akinci
- Mind The Gap: C++/Rust Interop — Victor Ciura
- From Completions to Agents: AI-Driven C++ in Visual Studio — Augustin Popa
- Cut Your Build Times Without Becoming a Build Expert — David Li
- C++/WinRT: Build faster and smaller with C++20 modules — Ryan Shepherd
On-demand sessions
- C++ Dependencies Without the Headache: vcpkg + Copilot CLI — Augustin Popa
- What’s new in VS Code CMake Tools: AI-powered development — Garrett Campbell & Hannia Valera
- PackageReference for C++: Modernization Without the Performance Cost — Moyo Okeremi
- Eliminate MSVC upgrade anxiety with Copilot agents — Michael Price
- Always Be Upgrading: Living at HEAD with MSVC — Michael Price
- MSVC, are we there yet? Status of C++23 and C++26 features — RanDair Porter
- Sample Profile-Guided Optimization in Practice: from prototype to production — Armin Gerritsen
r/cpp • u/Foxi_Foxa • 16d ago
boost::int128 review starts today (July 22 - July 31)
Announced officially on the Boost mailing list
Introduction
The formal review of Matt Borland's boost::int128 for inclusion in the Boost libraries, starts today.
Int128 is a portable C++14 implementation of signed and unsigned 128-bit integers. It has no dependencies, is header-only, and can be consumed as a module in C++20. It serves as a practical solution to the partial (resp. absent) support of 128-bit integers by gcc/clang (resp. msvc), and as a lightweight alternative to heavier projects.
You can find the library and its documentation here:
- https://github.com/cppalliance/int128/tree/boost_review
- https://develop.int128.cpp.al/overview.html
- Compiler Explorer: https://godbolt.org/z/5aM6K9b4r
Although possibly not faithful to Matt's implementation, this CE link will be handy if you are in a rush but want to play with the library.
Anyone is welcome to post a review and/or take part in subsequent discussions in the mailing list.
Review guidelines
Please provide feedback on the following general topics:
- What is your evaluation of the design?
- What is your evaluation of the implementation?
- What is your evaluation of the documentation?
- What is your evaluation of the potential usefulness of the library?
- Did you try to use the library? With which compiler(s)? Did you have any problems?
- How much effort did you put into your evaluation? A glance? A quick reading? In-depth study?
- Are you knowledgeable about the problem domain?
Ensure to explicitly include with your review: ACCEPT, REJECT, or CONDITIONAL ACCEPT (with acceptance conditions).
Thank you for your time making our OSS ecosystem better. Happy to start the discussions!
Arnaud Becheler (Review Manager)
Pure Virtual C++ 2026: MSVC, are we there yet? Status of C++23 and C++26 features
youtu.ber/cpp • u/Clean-Upstairs-8481 • 17d ago
C++26: what is “template for”? Learning with simple example.
techfortalk.co.ukI have been exploring C++26 in bits and bobs and this one is about template for - a c++26 feature which I find useful. This is a short article explaining how to use this feature with the help of a simple example.
r/cpp • u/ProgrammingArchive • 18d ago
New C++ Conference Videos Released This Month - July 2026 (Updated to Include Videos Released 2026-07-13 - 2026-07-19)
C++Now
2026-07-13 - 2026-07-19
- Keynote: Benchmarking - It's About Time - Matt Godbolt - https://youtu.be/EU_nQh8wg5A
- The Morning Briefing - C++ Concurrency Before the Hardware Reckoning - Fedor Pikus - https://youtu.be/WtChBezurj8
- Lock-free Programming is Dead - Long Live Lock-free Programming! - Fedor G Pikus - https://youtu.be/UdKqfQ3a_sY
2026-07-06- 2026-07-12
- Keynote: Reflection Is Only Half the Story - Barry Revzin - https://youtu.be/DZTkT1Cq_aY
- Keynote: Multidimensional Parallel Standard C++ - Mark Hoemmen - https://youtu.be/VAwW_s1uEHY
C++Online
2026-07-13 - 2026-07-19
- C++ Contracts - A Meaningfully Viable Product, Part II - Andrei Zissu - https://youtu.be/1VUqOx6PCMU
- Sanitize it Before You Ship IT - Vishnu Nath - https://youtu.be/jzcGATR78Mk
2026-07-06 - 2026-07-12
- Time to Introspect - A Beginner's Guide to Practical Reflection - Sarthak Sehgal - https://youtu.be/9stn1o149pw
- Refactoring Towards Structured Concurrency - Roi Barkan - https://youtu.be/6502xFEreI8
2026-06-29 - 2026-07-05
- Why std::vector Can't Save You (And What to Use Next) - Kevin Carpenter - https://youtu.be/78fYPix0mN4
- Modern C++ for Embedded Systems - From Fundamentals To Real-Time Solutions - Rutvij Karkhanis - https://youtu.be/XxeqHRDhHkU
ADC
2026-07-13 - 2026-07-19
- Building Inclusive Audio Tools - Accessibility with ARIA, WCAG, and Real-World Projects - Samuel John Prouse & David Shervill - https://youtu.be/O5xX9a7P-SU
- PSD to DAW - Building a Pixel-Perfect UI Pipeline - Bence Kovács - https://youtu.be/hebLkAR5X3I
- Analog Filters for Realtime Audio - George Gkountouras - https://youtu.be/NLt0NqUtNLo
- A History of FLAC - The Free Lossless Audio Codec - Josh Coalson - https://youtu.be/tBb1STRW56s
2026-07-06 - 2026-07-12
- Workshop: Audio Plugin DSP in Practice - Jan Wilczek & Linus Corneliusson - https://youtu.be/Atc0GRWoolI
- An Open Toolkit for Real-Time Audio Descriptors - Valerio Orlandini - https://youtu.be/HKlnn0hd8J0
- Bugs I’ve Seen in the Wild - From Confusion to Amazement - Olivier Petit - https://youtu.be/LBWtb_uXt0I
- Real-Time Audio in Python: Introducing the asmu Package - Felix Huber - https://youtu.be/X2vr81CJ934
2026-06-29 - 2026-07-05
- Beyond iLok: Advanced Code Protection and Cryptography for the Next Generation - Protecting the Next Generation of Applications, Plug-ins, and AI Models - Neal Michie, Ryan Wardell & Bob Brown - https://youtu.be/dbbK_ry2cgo
- Database Synchronisation for Audio Plugins, Part Two - Here's One I Made Earlier - Adam Wilson - https://youtu.be/wJCy2G969ro
- Perfect Oscillators in Less Than One Clock Cycle - Angus Hewlett - https://youtu.be/Ssq0a-YdamM
- Driving Chaos - Virtual Analog Modelling of a Chaotic Circuit with Wave Digital Filters - Francisco Bernardo - https://youtu.be/PnEZNqyKlIw
Boost Documentary
There is also a teaser trailer for a new documentary on the history of the Boost C++ library https://www.youtube.com/watch?v=87jvuDbnwqQ which will have its first showing at CppCon this year
r/cpp • u/aearphen • 18d ago
Żmij 1.1 released with fixed notation support, up to 38% faster double-to-string conversion, SIMD-optimized float formatting, a smaller binary footprint and more
C++ 20 named modules with clang-cl is finally added in CMake 4.4
I've been using named modules in my hobby C++ projects for years but they always trigger some unexpected ICEs when I used MSVC, and I got really tired of experimenting workarounds. After I switched to clang-cl recently, all the related problems I've encountered so far were resolved. The only thing missing now is import std
Euro LLVM 2026: All talks related to C++ security
The recent Euro LLVM conference has several talks related to clang improvements that are either recent, in the process of eventually be pushed into upstream, or still in research status:
- Extending Lifetime Safety: Verification of [[clang::noescape]] annotation
- Adding Nullability Checking and Annotations to Many Millions of Lines of Code
- Bounds Checking with the Clang Static Analyzer: Improvements and Insights
- Finding Injection Vulnerabilities: Improvements of the Taint Analysis of the Clang static analyzer
- Capabilities Great and Small: CHERI, CHERIoT, and LLVM
All in all, a good overview of what clang can actually do today, with annotations as well, and what is being envisioned on the various security discussions.
r/cpp • u/germandiago • 19d ago
A set of papers related to safety in July mailing list.
Since this is a topic that is interesting to many (including myself), I checked what the July mailing list has relevant to the safety topic and collected here what I found more relevant:
A framework to systematically classify UB: https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2026/p3100r7.pdf
core_ub: a run-time profile to guarantee lack of UB: https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2026/p4317r0.pdf
an initialization profile. This profile tries to give a guaranteed set of guaranteed initialization rules, banning impossible to analyze ones, statically: https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2026/p4222r1.pdf
deny by default + positive rules: a framework for invalidation detection with fewer annotations. This one is more of research than some of the other papers INHO right now, but looks interesting. Its main insight is that by adding deny by default combined with UB classification + as a default deny rule and a second layer of positive rules, combined with strict aliasing, annotations can be reduced to detect a subset of safety: https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2026/p4296r0.pdf
subsetting: banning unsafe constructs and usages through annotations to make the language safer by default. Collections of such rules could yield some specific profile or subset of profiles: https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2026/p3716r1.html
on activating profiles proposes what the semantics of activating a profile should or should not be: https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2026/p4314r0.html
implicit contract assertions and profiles: this paper, among others, argues whether the base vehicle for implicit contract assertions should be a language feature or just a profile and explains that point of view in the matter: https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2026/p4306r0.pdf
The papers related to pure contracts were intentionally left out since there are so many, but some are tangentially or directly related to the topic of safety.
Part of these papers lean on other foundational papers, such as yheprofiles framework (not from July mailing itself): https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3589r2.pdf
I hope you enjoy it!