GCC Code Coverage Report


Directory: Fw/Types/
File: Optional.hpp
Date: 2026-09-03 21:15:04
Exec Total Coverage
Lines: 38 38 100.0%
Functions: 20 20 100.0%
Branches: 17 24 70.8%

Line Branch Exec Source
1 // ======================================================================
2 // \title Optional.hpp
3 // \author celskeggs
4 // \brief hpp file for Optional type
5 //
6 // \description
7 // A lightweight optional type for C++14 environments where
8 // std::optional (C++17) is not available.
9 //
10 // \copyright
11 // Copyright (C) 2025-2026 California Institute of Technology.
12 // ALL RIGHTS RESERVED. United States Government Sponsorship
13 // acknowledged.
14 //
15 // ======================================================================
16
17 #ifndef Fw_Optional_HPP
18 #define Fw_Optional_HPP
19
20 #include <Fw/Types/Assert.hpp>
21 #include <type_traits>
22
23 namespace Fw {
24
25 //! \brief Sentinel type representing the absence of a value in an Optional
26 struct None_t {
27 constexpr explicit None_t() {}
28 };
29
30 //! \brief Global constant representing an absent/empty optional value
31 constexpr None_t NONE = None_t();
32
33 //! \class Optional
34 //! \brief A type-safe container for an optional value
35 //!
36 //! Provides a C++14-compatible alternative to std::optional.
37 //! Only supports trivially copyable types (no non-trivial constructors,
38 //! destructors, or copy/move operators).
39 //!
40 //! \tparam T The type of the contained value. Must be trivially copyable.
41 //!
42 template <typename T>
43 class Optional {
44 static_assert(std::is_trivially_copyable<T>::value, "Fw::Optional only supports trivially copyable types");
45
46 T m_val;
47 bool m_engaged;
48
49 public:
50 // ----------------------------------------------------------------------
51 // Construction
52 // ----------------------------------------------------------------------
53
54 //! Construct an empty Optional
55 2 constexpr Optional() : m_val(), m_engaged(false) {}
56
57 //! Construct an empty Optional from NONE sentinel
58 constexpr Optional(const None_t& a) : Optional() { (void)a; }
59
60 //! Construct an Optional containing a value
61 1 constexpr Optional(const T& t) : m_val(t), m_engaged(true) {}
62
63 //! Copy constructor
64 2 Optional(const Optional& other) : Optional() {
65
2/2
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 1 times.
2 if (other.has_value()) {
66 1 *this = other.value();
67 }
68 2 }
69
70 //! Destructor (trivial — T must be trivially copyable)
71 ~Optional() = default;
72
73 // ----------------------------------------------------------------------
74 // Observers
75 // ----------------------------------------------------------------------
76
77 //! Check whether the Optional contains a value
78 //! \return true if a value is present
79
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 20 times.
40 bool has_value() const { return m_engaged; }
80
81 //! Access the contained value
82 //! \pre has_value() must be true
83 //! \return Mutable reference to the contained value
84 26 T& value() {
85 26 FW_ASSERT(m_engaged);
86 26 return m_val;
87 }
88
89 //! Access the contained value (const)
90 //! \pre has_value() must be true
91 //! \return Const reference to the contained value
92 3 const T& value() const {
93 3 FW_ASSERT(m_engaged);
94 3 return m_val;
95 }
96
97 //! Access the value or return a default
98 //! \return The contained value if present, otherwise the provided default
99
3/4
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 1 times.
2 T value_or(const T& default_value) const { return m_engaged ? m_val : default_value; }
100
101 // ----------------------------------------------------------------------
102 // Modifiers
103 // ----------------------------------------------------------------------
104
105 //! Reset the Optional to an empty state
106 3 void reset() { m_engaged = false; }
107
108 // ----------------------------------------------------------------------
109 // Assignment operators
110 // ----------------------------------------------------------------------
111
112 //! Assign a value into the Optional
113 12 Optional& operator=(const T& t) {
114 12 m_engaged = true;
115 12 m_val = t;
116 12 return *this;
117 }
118
119 //! Reset the Optional via NONE assignment
120 1 Optional& operator=(const None_t& a) {
121 (void)a;
122 1 reset();
123 1 return *this;
124 }
125
126 //! Copy assignment operator
127 2 Optional& operator=(const Optional& other) {
128
2/2
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 1 times.
2 if (other.has_value()) {
129 1 *this = other.value();
130 } else {
131 1 reset();
132 }
133 2 return *this;
134 }
135
136 // ----------------------------------------------------------------------
137 // Comparison operators
138 // ----------------------------------------------------------------------
139
140 //! Compare with NONE sentinel
141 3 bool operator==(const None_t& a) const {
142 (void)a;
143
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 return !m_engaged;
144 }
145
146 //! Compare with NONE sentinel (inequality)
147 2 bool operator!=(const None_t& a) const {
148 (void)a;
149
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 return m_engaged;
150 }
151
152 //! Equality comparison with another Optional
153 4 bool operator==(const Optional& other) const {
154
4/6
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 4 times.
✓ Branch 6 taken 1 times.
✓ Branch 7 taken 3 times.
4 if (m_engaged != other.m_engaged) {
155 1 return false;
156 }
157
3/4
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 2 times.
3 if (!m_engaged) {
158 1 return true;
159 }
160 2 return m_val == other.m_val;
161 }
162
163 //! Inequality comparison with another Optional
164 2 bool operator!=(const Optional& other) const { return !(*this == other); }
165 };
166
167 } // namespace Fw
168
169 #endif
170