Skip to content

Add Fw::Optional type for C++14 environments#165

Open
devin-ai-integration[bot] wants to merge 6 commits into
develfrom
devin/1781058534-optional-type
Open

Add Fw::Optional type for C++14 environments#165
devin-ai-integration[bot] wants to merge 6 commits into
develfrom
devin/1781058534-optional-type

Conversation

@devin-ai-integration

@devin-ai-integration devin-ai-integration Bot commented Jun 10, 2026

Copy link
Copy Markdown
Related Issue(s) nasa#4986
Has Unit Tests (y/n) y
Documentation Included (y/n) n (Doxygen-style comments in header)
Generative AI was used in this contribution (y/n) AI

Change Description

Adds Fw::Optional<T> — a lightweight, C++14-compatible optional type — to Fw/Types/.

namespace Fw {
struct Absent { constexpr explicit Absent() {} };
constexpr Absent ABSENT = Absent();

template <typename T>
class Optional {
    // union-based storage, bool engaged flag
    constexpr Optional();            // empty
    constexpr Optional(const T& t);  // engaged
    bool has_value() const;
    T& value();                      // asserts engaged
    const T& value_or(const T& default_value) const;
    void reset();
    Optional& operator=(const T& t);
    Optional& operator=(const Absent&);
    bool operator==(const Optional&) const;
    // ...
};
}

Key design choices vs. the fprime-vorago original:

  • Lives in Fw namespace (not Va416x0Types)
  • Member naming follows F' convention (m_ prefix)
  • Adds value_or(), copy assignment, and Optional-to-Optional equality
  • Comparison operators are const-correct
  • Only supports trivially-destructible T (documented, destructor is defaulted)

Rationale

std::optional is unavailable in C++14, yet the pattern is extremely useful for expressing nullable values safely. An Optional was already proven useful in fprime-vorago; this promotes it to the core framework so all F' projects can use it.

Testing/Review Recommendations

  • Unit tests in Fw/Types/test/ut/OptionalTest.cpp cover: default/value/copy construction, assignment, reset(), value_or(), ABSENT comparisons, struct and floating-point payloads, constexpr usage.
  • Verify the union-based approach compiles cleanly on target toolchains (ARM, etc.) with -std=c++14.
  • Confirm FW_ASSERT fires on value() access when empty (death tests not included — framework assert handling varies).

Future Work

  • Consider adding emplace() for in-place construction.
  • Consider serialization support (Fw::Serializable integration) if needed for telemetry.

AI Usage (see policy)

AI (Devin) was used for the full implementation: code generation, test authoring, and PR creation. The design is based on the existing fprime-vorago Optional.hpp by @celskeggs.

IAMAI

Link to Devin session: https://nasa-jpl-demo.devinenterprise.com/sessions/a3fd7acb122e42c8bf59b31bf2d4ae35


Open in Devin Review

Incorporates an Optional class into F Prime core, providing a
type-safe container for optional values in C++14 environments
where std::optional is unavailable.

Based on the implementation from fprime-vorago (Va416x0/Types/Optional.hpp),
adapted to use the Fw namespace and F Prime conventions.

Resolves nasa#4986

Co-Authored-By: michael.d.starch <michael.d.starch@jpl.nasa.gov>
@devin-ai-integration

Copy link
Copy Markdown
Author
Original prompt from michael.d.starch

Would you take a crack at: nasa#4986

@devin-ai-integration

Copy link
Copy Markdown
Author

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR that start with 'DevinAI' or '@devin'.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment, CI, and merge conflict monitoring

Co-Authored-By: michael.d.starch <michael.d.starch@jpl.nasa.gov>
devin-ai-integration[bot]

This comment was marked as resolved.

devin-ai-integration Bot and others added 3 commits June 10, 2026 02:40
Restricts Fw::Optional<T> to trivially copyable T via static_assert.
This makes the union-based storage well-defined: writing to any member
of a union of trivially-copyable types is safe regardless of which
member was last active.

Co-Authored-By: michael.d.starch <michael.d.starch@jpl.nasa.gov>
Co-Authored-By: michael.d.starch <michael.d.starch@jpl.nasa.gov>
Co-Authored-By: michael.d.starch <michael.d.starch@jpl.nasa.gov>
Comment thread Fw/Types/Optional.hpp
constexpr Optional() : m_dummy(0), m_engaged(false) {}

//! Construct an empty Optional from ABSENT sentinel
constexpr Optional(const Absent& a) : Optional() { (void)a; }
Comment thread Fw/Types/Optional.hpp Fixed
devin-ai-integration[bot]

This comment was marked as resolved.

- Remove constexpr from copy constructor: it calls non-constexpr
  members and cannot be evaluated at compile time in C++14.
- Return T by value from value_or() instead of const T&: since T is
  constrained to trivially copyable types this is equally efficient
  and avoids dangling references when a temporary is passed.

Co-Authored-By: michael.d.starch <michael.d.starch@jpl.nasa.gov>
Comment thread Fw/Types/Optional.hpp
constexpr Optional(const Absent& a) : Optional() { (void)a; }

//! Construct an Optional containing a value
constexpr Optional(const T& t) : m_val(t), m_engaged(true) {}
@github-actions

Copy link
Copy Markdown

Coverage report — base devel

No baseline branch coverage/devel found. This run becomes the seed once it lands on devel.

Overall (line): 81.26% (no baseline)
Regression threshold: 0.50% (line).

Regressions

(none over threshold)

Modules changed

(no measurable change)

New modules

Module Line Function Branch
CFDP/Checksum 71.15 57.14 53.85
Drv/AsyncByteStreamBufferAdapter 100.00 100.00 100.00
Drv/ByteStreamBufferAdapter 100.00 100.00 100.00
Drv/Ip 44.32 57.38 25.36
Drv/TcpClient 75.00 100.00 47.37
Drv/TcpServer 84.72 100.00 60.00
Drv/Udp 68.09 90.91 42.86
Fw/Buffer 81.25 89.47 58.62
Fw/DataStructures 98.48 96.95 83.21
Fw/Dp 94.83 96.67 95.95
Fw/FilePacket 75.24 89.06 54.30
Fw/Log 71.43 72.41 60.00
Fw/Logger 100.00 100.00 100.00
Fw/SerializableFile 90.00 100.00 79.41
Fw/Time 88.62 85.48 86.84
Fw/Tlm 53.76 60.00 37.50
Fw/Types 55.85 60.06 36.31
Os 18.07 19.52 14.52
Os/Generic 89.10 96.30 67.18
Os/Generic/Types 92.45 91.67 82.14
Os/Posix 62.40 84.21 44.10
Svc/ActiveRateGroup 100.00 100.00 92.31
Svc/ActiveTextLogger 79.05 90.00 71.23
Svc/AssertFatalAdapter 94.74 100.00 86.67
Svc/BufferAccumulator 88.00 94.12 74.49
Svc/BufferLogger 92.62 86.96 80.46
Svc/BufferManager 99.05 100.00 83.64
Svc/BufferRepeater 91.67 100.00 75.00
Svc/ChronoTime 100.00 100.00 100.00
Svc/CmdDispatcher 96.97 91.67 91.75
Svc/CmdSequencer 93.89 97.12 84.63
Svc/CmdSplitter 100.00 100.00 100.00
Svc/ComLogger 97.37 91.67 83.91
Svc/ComSplitter 100.00 100.00 100.00
Svc/ComStub 98.51 100.00 85.19
Svc/DpCatalog 78.00 100.00 66.27
Svc/DpManager 97.44 100.00 100.00
Svc/DpWriter 97.58 90.00 97.22
Svc/FileDownlink 84.15 90.91 71.90
Svc/FileManager 88.41 93.33 82.44
Svc/FileUplink 92.35 96.55 80.95
Svc/FileWorker 90.29 100.00 84.87
Svc/FprimeDeframer 100.00 100.00 97.92
Svc/FprimeFramer 100.00 100.00 95.45
Svc/FprimeRouter 88.89 100.00 78.26
Svc/FpySequencer 86.76 99.04 76.89
Svc/GenericHub 100.00 100.00 85.64
Svc/Health 100.00 100.00 88.66
Svc/LinuxTimer 97.06 100.00 82.35
Svc/OsTime 70.00 83.33 60.98
Svc/PassiveRateGroup 100.00 100.00 89.47
Svc/PolyDb 100.00 100.00 53.57
Svc/PosixTime 100.00 100.00 75.00
Svc/PrmDb 92.75 89.47 88.24
Svc/RateGroupDriver 100.00 100.00 68.75
Svc/SeqDispatcher 73.08 80.00 71.05
Svc/StaticMemory 100.00 100.00 100.00
Svc/SystemResources 98.63 100.00 76.19
Svc/TlmChan 77.59 85.71 63.03
Svc/TlmPacketizer 92.49 100.00 77.45
Svc/Version 96.10 100.00 86.96
Utils 20.04 26.44 24.07
Utils/Types 92.11 95.83 77.08

Modules without UTs

CFDP/Checksum/GTest, Drv/ByteStreamDriverModel, Drv/Interfaces, Drv/LinuxGpioDriver, Drv/LinuxI2cDriver, Drv/LinuxSpiDriver, Drv/LinuxUartDriver, Drv/Ports, Drv/Ports/DataTypes, FppTestProject/FppTest/interfaces, FppTestProject/FppTest/topology/async, FppTestProject/FppTest/topology/components/Comp, FppTestProject/FppTest/topology/components/Framework, FppTestProject/FppTest/topology/components/Receiver, FppTestProject/FppTest/topology/components/Sender, FppTestProject/FppTest/topology/guarded, FppTestProject/FppTest/topology/ports, FppTestProject/FppTest/topology/sync, FppTestProject/FppTest/topology/top_ports, FppTestProject/FppTest/topology/types, Fw/Cmd, Fw/Com, Fw/Comp, Fw/FilePacket/GTest, Fw/Fpy, Fw/Interfaces, Fw/Obj, Fw/Port, Fw/Ports/CompletionStatus, Fw/Ports/Ready, Fw/Ports/Signal, Fw/Ports/SuccessCondition, Fw/Prm, Fw/SerializableFile/test/TestSerializable, Fw/Sm, Fw/Test, Fw/Types/GTest, Os/Models, Svc/Cycle, Svc/DpPorts, Svc/Fatal, Svc/FatalHandler, Svc/FileDownlinkPorts, Svc/FprimeProtocol, Svc/Interfaces, Svc/PassiveConsoleTextLogger, Svc/Ping, Svc/PolyIf, Svc/Ports/CommsPorts, Svc/Ports/FilePorts, Svc/Ports/OsTimeEpoch, Svc/Ports/TlmPacketizerPorts, Svc/Ports/VersionPorts, Svc/Sched, Svc/Seq, Svc/Subtopologies/CdhCore, Svc/Subtopologies/ComCcsds, Svc/Subtopologies/ComFprime, Svc/Subtopologies/ComLoggerTee, Svc/Subtopologies/DataProducts, Svc/Subtopologies/FileHandling, Svc/Types/TlmPacketizerTypes, Svc/WatchDog, TestDeploymentsProject/Ref/PingReceiver, TestDeploymentsProject/Ref/RecvBuffApp, TestDeploymentsProject/Ref/SendBuffApp, TestDeploymentsProject/Ref/Top, TestDeploymentsProject/Ref/TypeDemo, cmake/test/data/TestDeployment/TestBuildAutocoder, cmake/test/data/TestDeployment/TestChainedAutocoder, cmake/test/data/TestDeployment/TestHeaderAutocoder, cmake/test/data/TestDeployment/TestTargetAutocoder, cmake/test/data/test-fprime-library/TestLibrary/TestComponent, cmake/test/data/test-fprime-library2/TestLibrary2/TestComponent

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