Repository navigation
Fix reflection of non-default-constructible and empty aggregates - #30
Merged
Merged
Conversation
MemberTypeOf created an `Object {}` to look at its members, so it needed a
default constructor. CallOnMembers, FoldMembers, CollectDifferences and the
type-only EnumerateMembers all go through it, and therefore failed to
compile for exactly the aggregates CountMembers learned to count recently.
It uses std::declval now.
Also fixed along the way:
- CallOnMembers, FoldMembers and Inspect rejected aggregates without
members, because their constraints ask for the type of the first member.
- Inspect failed to compile for members that are enums, optionals, ranges
or of any other type that is neither a string, a number nor an aggregate.
Enums are shown by value, optionals by their value or `nullopt`, ranges
as `[a, b]`, and anything else that cannot be formatted by its type name.
It also appends to the result directly instead of formatting every member
into a temporary string first.
- FoldMembers copied the initial value, and handed the accumulator to the
callable as an lvalue, costing a copy per member for callables taking it
by value. Both are moved now, which makes move-only accumulators usable.
- CallOnMembersWithoutName passed a reference type as the member type. It
is the plain member type now, as in MemberTypeOf.
- TypeNameOf truncated names containing the character sequence that ends
the name in the compiler's function signature (e.g. `int[3]`), and on
MSVC cut everything before the first space, so that `unsigned int` became
`int`. Only a leading class-key is removed there now.
- ToTuple uses a structured binding pack where available, instead of the
chain of 150 branches, which the compiler then no longer has to parse.
- <concepts> is used by the header, but was only included transitively.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ar6Ahymw9LhLsnM324z5cV
Signed-off-by: Yaraslau Tamashevich <yaraslau.tamashevich@gmail.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
#29 taught
CountMembersto count aggregates that have a member without a default constructor, but the rest of the library still could not handle them:MemberTypeOfcreated anObject {}to look at its members, andCallOnMembers,FoldMembers,CollectDifferencesand the type-onlyEnumerateMembersall go through it. This is the second blocker described in LASTRADA-Software/Lightweight#50. The other changes come out of a review of the whole header for bugs and accidental copies.Changes
MemberTypeOfusesstd::declvalinstead ofObject {}. A test covers the shape from the Lightweight issue: a field type with a deleted default constructor and a greedy variadic constructor template.CallOnMembers,FoldMembersandInspectrejected aggregates without members, because their constraints ask for the type of the first member.Inspectfailed to compile for members that are enums, optionals, ranges, or anything else that is neither a string, a number nor an aggregate. Enums are now shown by value, optionals by their value ornullopt, ranges as[a, b], a nullchar const*asnull, and anything that cannot be formatted by its type name in angle brackets. Output for the previously supported types is unchanged. It also appends to the result directly rather than formatting each member into a temporary string.FoldMemberscopied the initial value and passed the accumulator to the callable as an lvalue, which cost one copy per member for callables taking it by value. Both are moved now, so move-only accumulators work. A callable taking the accumulator as a non-const lvalue reference no longer compiles.CallOnMembersWithoutNamepassed a reference type (int&) as the member type; it is the plain member type now, as inMemberTypeOf.TypeNameOftruncated names such asint[3], and on MSVC removed everything before the first space, sounsigned intbecameint. Only a leading class-key is removed there now.ToTupleuses a structured binding pack where the compiler provides one, so the chain of 150 branches is skipped by the preprocessor. Parsing the header beyond its standard includes drops from roughly 118 ms to 11 ms on gcc and from 37 ms to 13 ms on clang.<concepts>is included directly, andToTuple/GetMemberAtdocument that their result refers into the argument.A copy-counting member type confirmed that
ToTuple,GetMemberAt,EnumerateMembers,CallOnMembers,CallOnMembersWithoutNameandCollectDifferencesmake no copies or moves of members.Current Lightweight
masterbuilds against this branch without errors or warnings.🤖 Generated with Claude Code
https://claude.ai/code/session_01Ar6Ahymw9LhLsnM324z5cV