40. Hotpath Concepts
In tight HFT loops, we must enforce compile-time constraints that avoid accidental copies and guarantee nothrow updates. Concepts can encode structural and exception guarantees without runtime overhead. Consider the following minimal constraint around a price/quantity update.
struct Tick { int px; int qty; };
template<class T>
concept QtyUpdatable = requires(T t) { { ++t.qty } noexcept -> std::same_as<int&>; };
template<QtyUpdatable T>
inline void bump(T& t) noexcept { ++t.qty; }
Tick t{100,1};
int main(){ bump(t); return t.qty; }
Part 1.
Does QtyUpdatable precisely enforce the intended properties for hot-path updates? Identify any pitfalls and propose an improved constraint to avoid unintended copies and proxy types.
Part 2.
(1) Does requires(T t) copy t? How avoid copies while checking constraints?
(2) Is std::same_as<int&> sufficient to reject proxy references or bitfields?
(3) How would you generalize to accept Tick* or std::span<Tick>?
(4) What are overload resolution risks between constrained and unconstrained bump on hot paths?
(5) Does noexcept in the requires-clause affect codegen or only substitution? Explain.
Answer
Answer (Part 1)
QtyUpdatable checks ++t.qty is noexcept and yields int&, but requires(T t) forms a prvalue and can copy. Prefer binding the constraint to an lvalue: use requires(T& u) { { u.qty } -> std::same_as<int&>; { ++u.qty } noexcept; } to avoid copies and reject proxies/const types; bump(T&) noexcept remains the sole hot-path call.
Answer (Part 2)
(1) Yes; it constructs a prvalue and may copy. Use requires(T& t) or std::type_identity_t<T>& to avoid copies/decay.
(2) It rejects anything not yielding an int&, including proxies and bitfields. That’s typically desirable for predictable ABI and latency.
(3) Constrain pointer-like via std::is_pointer_v<T> and dereference into QtyUpdatable<std::remove_pointer_t<T>>. For spans, require data()/size() and update elements.
(4) Multiple viable constrained overloads can be ambiguous and inhibit inlining. Prefer one most-specific constrained API per hot path.
(5) In the requires-clause, noexcept affects constraint satisfaction only. Function-level noexcept influences codegen/unwinding and can enable optimizations.