Skip to content

Serialize optional<T> for T's that have no default constructor#352

Merged
gennaroprota merged 1 commit into
developfrom
feature/serialize-optional-of-non-default-constructible-type
Jul 22, 2026
Merged

Serialize optional<T> for T's that have no default constructor#352
gennaroprota merged 1 commit into
developfrom
feature/serialize-optional-of-non-default-constructible-type

Conversation

@gennaroprota

Copy link
Copy Markdown
Collaborator

The value of an optional<T> is now handled like a single element of a standard library container: when T is default constructible, it is serialized in place, exactly as before; otherwise, construction is routed through save_construct_data/load_construct_data so that T can be reconstructed on load. This lets optional<T> be serialized for types that cannot or should not provide a default constructor (const-qualified members, third party classes, and so on).

The default-constructible path is left byte for byte unchanged, so archives written by earlier versions keep the same layout. The construct-data path writes an extra item_version plus whatever save_construct_data emits, which is new wire content only for types that previously could not be serialized at all, so no existing archive is affected.

Loading reconstructs the value with detail::stack_construct, which placement-constructs the object through load_construct_data before the value is read. This is unlike the pre-2017 implementation, which serialized into unconstructed storage (detail::stack_allocate), so the reliability concern that motivated the earlier restriction does not apply here.

Closes issue #121.

The value of an `optional<T>` is now handled like a single element of a
standard library container: when `T` is default constructible, it is
serialized in place, exactly as before; otherwise, construction is
routed through `save_construct_data`/`load_construct_data` so that `T`
can be reconstructed on load. This lets `optional<T>` be serialized for
types that cannot or should not provide a default constructor
(const-qualified members, third party classes, and so on).

The default-constructible path is left byte for byte unchanged, so
archives written by earlier versions keep the same layout. The
construct-data path writes an extra `item_version` plus whatever
`save_construct_data` emits, which is new wire content only for types
that previously could not be serialized at all, so no existing archive
is affected.

Loading reconstructs the value with `detail::stack_construct`, which
placement-constructs the object through `load_construct_data` before the
value is read. This is unlike the pre-2017 implementation, which
serialized into unconstructed storage (`detail::stack_allocate`), so the
reliability concern that motivated the earlier restriction does not
apply here.

Closes issue #121.
@gennaroprota
gennaroprota added this pull request to the merge queue Jul 22, 2026
Merged via the queue into develop with commit 7132a62 Jul 22, 2026
86 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant