#stdlib
21 posts tagged #stdlib.
What C++23 and C++26 promise about a moved-from function wrapper
None of the standard function wrappers promises an empty source after a move: std::function, move_only_function and copyable_function all leave it valid but unspecified. libstdc++ 16.1 empties all three, libc++ trunk keeps a copy in std::function and does not ship the other two. A small wrapper that states its own move works on both.
Portable SIMD is in C++26, and you can try it now
C++26 adds <simd>, a portable vector type that compiles to SSE, AVX, or NEON without a single intrinsic. GCC 16.1 does not ship the standard header yet, but the experimental version it grew from works today, and the programming model is the same: declare a vector, use the arithmetic operators, let the library pick the width.
Hand a task to another thread without leaving a copy behind
Two ways to stop a std::function from leaving a copy behind when it crosses to another thread: empty the source with an exchange, or box the task in a shared_ptr at the entry point. In a demo on libc++, the plain by-value chain destroys the task on the sending thread and both fixes destroy it on the worker.
libstdc++ on GCC trunk rejects a pair that binds a temporary
On GCC trunk, building a std::pair or std::tuple whose reference member binds to a temporary is an error from C++11 to C++26. GCC 16.2 rejects it only from C++20 on. The same weeks brought a libstdc++ fix for CVE-2026-102010, now on the GCC 14, 15 and 16 branches, and a std::bitset fix that is on trunk only. Compiler Explorer runs show 16.2 and trunk side by side.
C++26 removes the initializer_list constructor of std::span
With the initializer_list constructor that C++26 had added, std::span<const bool> s{ptr, n} builds a two-element span of bools, and GCC 15 compiles it with a warning. P4144R1 removes the constructor, the 2026-03 LWG motion put that into the C++ working draft, and libstdc++ 16 and libc++ 23 no longer have it. Compiler Explorer runs show each library side by side.
std::optional can finally hold a reference
std::optional<T&> was ill-formed for fourteen years, so everyone used a raw pointer and wrote a comment explaining that null means absent. C++26 makes it legal: rebinding assignment, no allocation, and a value type you can return. It compiles and runs on GCC 16.1 today, though libstdc++ has not yet set the feature-test macro.
std::function_ref borrows a callable instead of owning it
C++26 adds std::function_ref, the non-owning counterpart to std::function. It is the right parameter type for a callback you will invoke but not store: it copies nothing, allocates nothing, and binds equally to a capturing lambda or a plain function. It is to std::function what string_view is to string.
A moved-from std::function can still hold the callable
The standard leaves a moved-from std::function valid but unspecified. libc++ keeps a copy of a small callable in the source, libstdc++ empties it. A Qt HarmonyOS bug filed on 2026-10-12 shows the cost: a task queued to another thread was destroyed on the thread that sent it.
views::concat iterates several containers as one range
C++26 adds std::views::concat, a view that presents several ranges as a single sequence without copying any of them. The containers can be different types holding the same elements, the result composes with every other adaptor, and GCC 16.1 ships it today.
The hardened standard library turns an out-of-bounds read into a stop
GCC checks an out-of-bounds vector::operator[] at -O0 and stops checking at -O2, so the build you debug is guarded and the build you ship is not. One macro carries the check into the optimised build: -D_GLIBCXX_ASSERTIONS for libstdc++, _LIBCPP_HARDENING_MODE for libc++, _MSVC_STL_HARDENING for the MSVC STL. Google has reported this class of hardening cut its production segfault rate by about a third.
Four range views headed for the standard library
The 2026-07 mailing adds a concentrated wave of range adaptors: views::unique for adjacent duplicates, views::take_last and views::drop_last for tail slicing, and views::cycle for endless repetition. None ship yet, so the demo is what you write today to get the same results, which is exactly the boilerplate each proposal collapses into one named view.
std::array became compile-time in pieces, and the algorithms went last
std::array's own members have been constexpr since C++17, but sorting one at compile time only became possible in C++20, when the algorithms caught up. That two-standard gap is why older lookup-table code hand-rolls its sorting. Here is a table built, squared and sorted entirely during compilation.
Boost and Abseil start deleting their C++14 shims
Two release notes nine days apart point the same way. Boost 1.92 tells Heap and Lockfree users that C++14 support ends here, and Abseil's August LTS deprecates absl::void_t in favour of the standard one. Both are removing code that only ever existed because C++17 was not yet safe to assume.
std::constant_wrapper carries a compile-time value as an argument
A template parameter is a compile-time value you cannot pass as an argument. A function argument is a runtime value you cannot use as a template parameter. C++26's std::constant_wrapper is an empty object that carries a compile-time value, so it crosses that line: arithmetic on it stays constant, and the result still works as an array extent. GCC 16.1 ships it.
Converting between std::function and copyable_function nests them
std::function and std::copyable_function are both type-erased callable wrappers and neither recognises the other. Converting between them does not unwrap and rewrap the lambda inside; it wraps the whole previous wrapper. Round-trip in a loop and every call walks a chain of indirections. In this run, 200 round trips made the same calls several hundred times slower.
std::indirect makes PImpl copyable without writing a copy constructor
PImpl with unique_ptr costs you the special members: hand-written copy operations, a destructor defined where Impl is complete, and const that stops at the pointer. C++26's std::indirect is an indirect value instead of an owning pointer, so it copies deeply and propagates const, and all five special members can be defaulted. GCC 16.1 ships it.
std::mdspan views one flat buffer as a matrix
std::mdspan is C++23's non-owning multidimensional view. It separates storage (a flat buffer you already have) from shape (extents) from indexing (a layout), so one std::vector becomes a 3x4 matrix with real m[r, c] indexing and no copy. GCC 16.1 ships it, and Mark Hoemmen's C++Now 2026 keynote is on where it and standard parallelism go next.
std::inplace_vector is a vector that never touches the heap
C++26 adds std::inplace_vector<T, N>, a sequence container with a fixed compile-time capacity whose storage lives inside the object. It gives you a vector's dynamic size and push_back with zero heap allocation, which is exactly what embedded, real-time, and hot-path code has been hand-rolling for decades. GCC 16.1 ships it now.
Three small C++26 string fixes you will use every day
C++26 quietly closes three long-standing paper cuts in the string library: you can finally write string + string_view, build a stringstream straight from a string_view, and construct a bitset from a view without a temporary. None of them are flashy, all of them remove a copy or a conversion you have been writing for years. Verified on GCC 16.1 and clang-p2996.
std::rotate: how libstdc++ and libc++ actually differ
Raymond Chen's June 2026 series on The Old New Thing exposed a surprising fact: libstdc++ and libc++ implement std::rotate with completely different algorithms. libstdc++ swaps left-to-right and ends at n-1 swaps with good locality. libc++ decomposes the rotation into gcd(a, n) cycles and hits ~n/2 swaps but with poor locality. Which is faster depends entirely on your input shape.
Could C++ handle an ABI break? The 2026 case
Two pieces dropped in the same week: Luis Caro Campos' CppCon 2025 talk arguing package managers make ABI breaks manageable, and an HFT University article claiming a 58x P99 latency gap between Rust's and C++'s stdlib. The ABI debate is back. Here is what both sides are saying, and what C++26 shipped despite the constraint.