P2964R2 — User-defined element types in std::simd through trait-based vectorizable definition
(13 items)
LEWG
This paper proposes extending std::simd to support user-defined element types by replacing the current closed list of vectorizable types (arithmetic types and std::complex) with a trait-based definition based on trivial copyability, power-of-2 size, and alignment constraints. The change enables type-safe strong typedefs, enumerations, std::byte, and domain-specific numeric types to be used as simd element types while maintaining full backward compatibility and identical semantics for existing types. Implementation experience with Clang 20 and Intel oneAPI 2025.0 demonstrates that leading compilers can generate assembly identical to built-in arithmetic types for user-defined types through element-wise inference.
-
§9.3 (supported_binary_op concept) — Missing braces in compound requirement: BinaryOp{}(a, b) -> std::same_as
is parsed as a simple-requirement using operator->, not a return-type-requirement. Must be { BinaryOp{}(a, b) } -> std::same_as ; to match the correct syntax used in supported-unary-op immediately above. [1] - §9.6 (shift operator constraints) — Wording constrains shift operators by reference to "the corresponding standard transparent function object," but no such function objects exist for << and >>. The paper's own note in §9.6 acknowledges this. The constraint either needs direct specification or an explicit dependency on a paper (e.g., P4006) that introduces them. [2]
- §9.3 (supported_binary_op concept) — Ternary operator (?:) in supported-unary-op vs. conjunction/disjunction (&&/||) in supported_binary_op: the two forms differ in constraint subsumption behavior. Sibling concepts in the same block should use the same formulation. [3]
- §9.3 (supported_binary_op concept) — Naming inconsistency: supported-unary-op uses hyphens (exposition-only convention) while supported_binary_op uses underscores. Should be supported-binary-op. [4]
- §9.3 (supported_binary_op body) — Identifier mismatch: the concept is defined as promotable-type but referenced inside supported_binary_op as promotable_type (underscore). The underscore form is undeclared. [5]
-
§9.3 (supported-unary-op vs. supported_binary_op) — Inconsistent std:: qualification: supported-unary-op uses unqualified same_as
while supported_binary_op uses std::same_as in the same proposed wording block. [6] - §8 (Design Options for Enum and Byte Support) — Case mismatch on template parameter: declared as IntegerType but used as Integertype in the return type. These are different identifiers. [7]
- §9.5, drafting note (UDT-to-UDT conversion) — Missing space: "static_castto" should be "static_cast to". [8]
- §2 (Introduction) — Grammar error: "while naturally extend" should be "while naturally extending". [9]
- §2.3 (Core Proposal) — Grammar error: "is a now vectorizable" — extraneous article. Should be "is now vectorizable" or "is now a vectorizable type". [10]
- §2.3 (Core Proposal) — Missing article: "change definition" should be "change the definition". [11]
- §4.3 (Alignment Constraint) — Wrong word form: "constrain" (verb) used where the noun "constraint" is needed. [12]
References — Anthropic Citations API
[1]
"(!promotable_type && requires(T a, T b) { BinaryOp{}(a, b) -> std::same_as; });"
"(!promotable_type
[2]
"concept supported-unary-op = and concept supported_binary_op ="
"concept supported-unary-op = and concept supported_binary_op ="
[3]
"( promotable_type && requires(T a, T b) { BinaryOp{}(a, b); }) || (!promotable_type && requires(T a, T b) { BinaryOp{}(a, b) -> std::same_as; });"
"( promotable_type
[4]
"constexpr rebind_t>"
"constexpr rebind_t
[5]
"requires(T a) { { UnaryOp{}(a) } -> same_as; }; and requires(T a, T b) { BinaryOp{}(a, b) -> std::same_as; }"
"requires(T a) { { UnaryOp{}(a) } -> same_as
[6]
"supported-binary-op is true, where Op is the corresponding standard transparent function object"
"supported-binary-op
[7]
"Exclusion with this constrain is likely to be rare in practice"
"Exclusion with this constrain is likely to be rare in practice"
[8]
"A type T is a now vectorizable if:"
"A type T is a now vectorizable if:"
[9]
"trait-based constraints that handle all existing types while naturally extend support to enumerations"
"trait-based constraints that handle all existing types while naturally extend support to enumerations"
[10]
"allowing static_castto use whichever is available"
"allowing static_castto use whichever is available"
[11]
"The core idea of our proposal is to change definition of a vectorizable type"
"The core idea of our proposal is to change definition of a vectorizable type"
[12]
"concept supported-unary-op = ... promotable-type ? requires(T a) { UnaryOp{}(a); } : requires(T a) { { UnaryOp{}(a) } -> same_as; }; vs. concept supported_binary_op = ( promotable_type &&..."
"concept supported-unary-op = ... promotable-type
Summary: This paper proposes replacing the closed list of vectorizable types in std::simd with a trait-based mechanism, allowing user-defined types (structs, enums, std::byte) to opt in to SIMD operations by specializing simd_traits. It introduces exposition-only concepts and modifies operator constraints to support this extensibility.
Pipeline: Discovery (Anthropic Opus + Citations API) → Verification Gate (OpenRouter Opus) → Report Writer (OpenRouter Opus)
Provenance: All references are machine-verified character positions from the Anthropic Citations API — deterministic, exact substrings, not model-generated quotes.
Provenance: All references are machine-verified character positions from the Anthropic Citations API — deterministic, exact substrings, not model-generated quotes.