Skip to content

Commit f84dbf5

Browse files
authored
Merge pull request #1015 from SignalK/fix/883-nullable-bool
fix(types): make Nullable<bool> a compile error (#883)
2 parents 46808b0 + 42e3028 commit f84dbf5

3 files changed

Lines changed: 14 additions & 20 deletions

File tree

src/sensesp/types/nullable.cpp

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,5 @@ uint64_t Nullable<uint64_t>::invalid_value_ = 0xffffffffffffffffLL;
3636
template <>
3737
int64_t Nullable<int64_t>::invalid_value_ = 0x7fffffffffffffffLL;
3838

39-
template <>
40-
bool Nullable<bool>::invalid_value_ = false;
41-
4239

4340
} // namespace sensesp

src/sensesp/types/nullable.h

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
#ifndef SENSESP_SRC_SENSESP_TYPES_NULLABLE_H_
22
#define SENSESP_SRC_SENSESP_TYPES_NULLABLE_H_
33

4+
#include <type_traits>
5+
46
#include "ArduinoJson.h"
57

68
namespace sensesp {
@@ -13,9 +15,19 @@ namespace sensesp {
1315
* value is invalid only when it equals that sentinel. A default-constructed
1416
* Nullable holds T{} (0), so it is valid for types whose sentinel differs from
1517
* 0; use Nullable<T>::invalid() to obtain the invalid value explicitly.
18+
*
19+
* Nullable<bool> is intentionally unsupported: bool has only two values, so
20+
* there is no spare bit pattern to reserve as an invalid sentinel without
21+
* making one of `true`/`false` indistinguishable from "missing". Use a plain
22+
* bool, or a wider type if you need a distinct invalid state.
1623
*/
1724
template <typename T>
1825
class Nullable {
26+
static_assert(
27+
!std::is_same<T, bool>::value,
28+
"Nullable<bool> is not supported: bool has no spare sentinel value. Use a "
29+
"plain bool, or a wider type if a distinct invalid state is needed.");
30+
1931
public:
2032
Nullable() : value_{} {}
2133
Nullable(T value) : value_{value} {}
@@ -55,7 +67,6 @@ class Nullable {
5567
typedef Nullable<int> NullableInt;
5668
typedef Nullable<float> NullableFloat;
5769
typedef Nullable<double> NullableDouble;
58-
typedef Nullable<bool> NullableBool;
5970

6071
template <typename T>
6172
void convertFromJson(JsonVariantConst src, Nullable<T> &dst) {

test/system/test_nullable/nullable_test.cpp

Lines changed: 2 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@
99
* sentinel (e.g. float -> -1e9, uint8_t -> 0xff). A value is "invalid" only
1010
* when it equals that sentinel. A default-constructed Nullable holds T{} (0),
1111
* which is therefore VALID for types whose sentinel differs from 0 (int,
12-
* float, uint8_t) and INVALID only for bool, whose sentinel is false.
12+
* float, uint8_t). Nullable<bool> is unsupported and fails to compile (bool
13+
* has no spare sentinel value); see #883.
1314
*/
1415

1516
#include <Arduino.h>
@@ -57,20 +58,6 @@ void test_nullable_default_float_is_valid_zero() {
5758
TEST_ASSERT_FLOAT_WITHIN(0.0001f, 0.0f, n.value());
5859
}
5960

60-
void test_nullable_bool_sentinel_is_false() {
61-
// bool's invalid sentinel is `false`, so a default/false Nullable<bool> is
62-
// invalid and a value of `false` is indistinguishable from invalid.
63-
NullableBool d;
64-
TEST_ASSERT_FALSE(d.is_valid());
65-
66-
NullableBool t = true;
67-
TEST_ASSERT_TRUE(t.is_valid());
68-
TEST_ASSERT_TRUE(static_cast<bool>(t));
69-
70-
NullableBool f = false;
71-
TEST_ASSERT_FALSE(f.is_valid());
72-
}
73-
7461
// ---------------------------------------------------------------------------
7562
// ptr() exposes the underlying storage
7663
// ---------------------------------------------------------------------------
@@ -140,7 +127,6 @@ void setup() {
140127
RUN_TEST(test_nullable_invalid_sentinel_is_not_valid);
141128
RUN_TEST(test_nullable_value_is_valid);
142129
RUN_TEST(test_nullable_default_float_is_valid_zero);
143-
RUN_TEST(test_nullable_bool_sentinel_is_false);
144130
RUN_TEST(test_nullable_ptr_mutates_value);
145131
RUN_TEST(test_nullable_copy_assignment);
146132
RUN_TEST(test_nullable_to_json_invalid_is_null);

0 commit comments

Comments
 (0)