Document: P3856R4
Authors: Jagrut Dave, Alisdair Meredith
Date: 2026-01-17
Audience: LEWG/LWG
Addresses US NB comment 49. The standard uses "structural type" in several places (NTTPs, std::array) and library mandates require it, but there's no way to query whether a type is structural. This paper adds is_structural_type(info) as a reflection metafunction and std::is_structural<T> as a type trait. Comes with a proof-of-concept implementation on Bloomberg's Clang fork using P2996 reflection.
It's wild that we've had structural types since C++20 NTTPs and there's been no way to check at compile time whether a type qualifies. Library code that wants to wrap values as NTTPs has been guessing. The motivating example with
const_wrapperis exactly the pattern I've wanted - SFINAE-friendly selection between NTTP path and runtime path based on whether the type is structural.Section 4 on type traits vs metafunctions is a valuable discussion beyond the scope of this paper. Should
is_structural<T>andis_structural_type(^^T)be independent implementations or should one wrap the other? The paper argues independence - different paradigms, different side effects, different error handling. That seems right.The proof of concept is interesting because it shows what P2996 reflection can and can't do. It can check public/non-mutable/structural recursively. It can't query "is this function constexpr" or "is this a lambda closure type" - so the literal type check is conservative. The paper identifies these as gaps that future metafunctions should fill.
Bloomberg papers tend to be focused and implementable. Two authors, one metafunction, one type trait, proof of concept on their Clang fork. This is what a good NB comment resolution looks like.
Section 3.3 notes that
std::is_literal_typewas removed in C++20 and there's no reflection replacement. The paper's implementation has to work around this absence. Feels like we removed a useful trait and never replaced it.R4 removed
is_destructurable_typeper LEWG feedback and dropped the access context parameter from the signature. Clean scoping - one concept, one metafunction, one trait. Ship it.The paper includes a Godbolt link to the proof of concept. You can actually run the static_asserts. More papers should do this.