-
Notifications
You must be signed in to change notification settings - Fork 264
Description
Title: Proposal: NTuple-style Named Field Types to Improve Safety and Toolability in Generic C++
Summary
This proposal introduces the concept of type-level field names (as implemented in the NTuple as a structured and type-safe alternative to positionally-indexed tuples, variadic argument unpacking, and ad-hoc std::tuple
-based APIs. The core idea is to bind values to compile-time field types rather than string keys or runtime identifiers, enabling:
- safer generic programming,
- clearer error messages,
- more predictable introspection,
- and flexible interfaces like named function arguments with default values and compile-time validation.
Benefits
1. Improves Safety: Eliminates a Class of Bugs in Generic Code
Using traditional std::tuple
or std::pair
-based interfaces, accidental index mismatches or reorderings are easy and common. These can result in subtle logic bugs or invalid memory use.
By contrast, NTuple-style types carry the name of the field in the type system, so:
- Assignments like
arg1 = 42
are strongly typed. - Function calls like
my_function(arg2 = 5, arg1 = 7)
cannot silently misplace arguments. - Named fields are validated at compile time, making it impossible to accidentally pass
foo = 10
to a function that expects onlyarg1
,arg2
,arg3
.
✅ This could eliminate a measurable portion of argument ordering bugs in generic APIs and user-defined function wrappers.
2. Improves Toolability: Enables Structural Reflection Without Syntax Extensions
Every field name is a type. Every value is wrapped in a consistent container. As a result:
- Introspection (e.g. printing all members, subsetting, transforming fields) becomes trivial using metaprogramming techniques, without requiring language-level reflection.
- Tools and IDEs can infer structure and suggest completions for field names, aiding discoverability and correctness.
✅ This reduces the need for tool-specific hacks, macros, or external schemas to describe structured data.
3. Eliminates Guidance: Simplifies Common Interface Design Patterns
Named function arguments (via bind_args
) replace the need for:
- Overloading permutations of argument sets
- Boilerplate argument-parsing code
- Guidelines around argument ordering and documentation
This supports several goals of the C++ Core Guidelines, particularly:
- [F.16: Prefer using a named struct when passing multiple arguments](https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#f16-prefer-using-a-named-structure-when-passing-arguments)
- [ES.45: Avoid “magic constants”; use symbolic names instead](https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#es45-avoid-magic-constants)
✅ This approach makes default safety patterns the path of least resistance, removing the need for guidance to prevent misuse.
Alternatives Considered
-
std::tuple
+ helper functions/macros- Fragile, lacks field names at the type level, hard to maintain or introspect.
-
Named struct types
- Good safety but inflexible; doesn't compose well or support dynamic field generation.
-
Reflection proposals
- More powerful, but also heavier and farther from standardization. NTuple achieves much of the same introspection with today’s C++.
Quantifiable Impact
- Reduces misuse of variadic and tuple-based APIs.
- Enables compile-time validation of field sets in user-defined interfaces.
- Improves debuggability via named, printable structures.
- Simplifies a large class of argument-handling boilerplate in library and application code.
PS: Thank you for the great work and your fantastic presentations