add expected helper class (#1321)

Co-authored-by: Matthew Kennedy <makenne@microsoft.com>
This commit is contained in:
Matthew Kennedy 2020-04-18 22:53:04 -07:00 committed by GitHub
parent c5a0da2db7
commit 7f60384c75
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 59 additions and 28 deletions

View File

@ -22,7 +22,7 @@ class FuncChain<> {
protected:
SensorResult convert(float input) const {
// Base case is the identity function
return {true, input};
return input;
}
void showInfo(Logging* logger, float testInputValue) const {
@ -48,7 +48,7 @@ public:
if (currentStep.Valid) {
return TBase::convert(currentStep.Value);
} else {
return {false, 0};
return unexpected;
}
}

View File

@ -13,18 +13,18 @@ void ResistanceFunc::configure(float supplyVoltage, float pullupResistor) {
SensorResult ResistanceFunc::convert(float raw) const {
// If the voltage is very low, the sensor is a dead short.
if (raw < 0.05f) {
return {false, 0.0f};
return unexpected;
}
// If the voltage is very high (98% VCC), the sensor is open circuit.
if (raw > (m_supplyVoltage * 0.98f)) {
return {false, 1e6};
return unexpected;
}
// Voltage is in a sensible range - convert
float resistance = m_pullupResistor / (m_supplyVoltage / raw - 1);
return {true, resistance};
return resistance;
}
void ResistanceFunc::showInfo(Logging* logger, float testInputValue) const {

View File

@ -13,7 +13,7 @@ SensorResult ThermistorFunc::convert(float ohms) const {
// This resistance should have already been validated - only
// thing we can check is that it's non-negative
if (ohms <= 0) {
return {false, 0};
return unexpected;
}
float lnR = logf(ohms);
@ -26,7 +26,7 @@ SensorResult ThermistorFunc::convert(float ohms) const {
float celsius = convertKelvinToCelcius(kelvin);
return {true, celsius};
return celsius;
}
void ThermistorFunc::configure(thermistor_conf_s &cfg) {

View File

@ -92,7 +92,7 @@ bool Sensor::Register() {
// Next check for mock
if (entry->useMock) {
return {true, entry->mockValue};
return entry->mockValue;
}
// Get the sensor out of the entry
@ -103,7 +103,7 @@ bool Sensor::Register() {
}
// We've exhausted all valid ways to return something - sensor not found.
return {false, 0};
return unexpected;
}
/*static*/ float Sensor::getRaw(SensorType type) {

View File

@ -48,23 +48,11 @@
#pragma once
#include "sensor_type.h"
#include "expected.h"
#include <cstddef>
struct SensorResult {
const bool Valid;
const float Value;
// Implicit conversion operator to bool, so you can do things like if (myResult) { ... }
constexpr explicit operator bool() const {
return Valid;
}
// Easy default value handling
constexpr float value_or(float valueIfInvalid) const {
return Valid ? Value : valueIfInvalid;
}
};
using SensorResult = expected<float>;
// Fwd declare - nobody outside of Sensor.cpp needs to see inside this type
struct SensorRegistryEntry;
@ -156,7 +144,7 @@ private:
return 0;
}
SensorType m_type;
const SensorType m_type;
// Get this sensor's index in the list
constexpr size_t getIndex() {

View File

@ -41,7 +41,7 @@ public:
return {false, value};
}
return {true, value};
return value;
}
protected:

43
firmware/util/expected.h Normal file
View File

@ -0,0 +1,43 @@
/**
* @file expected.h
* @brief This utility class provides a way for a function to accept or return a value that may be invalid.
*
* For example, suppose there needs to be a solution for prevention of divide by zero. One could write this function:
*
* expected<int> my_divide(int num, int denom) {
* if (denom == 0) return unexpected;
* return num / denom;
* }
*
* @date April 18, 2020
* @author Matthew Kennedy, (c) 2020
*/
#pragma once
template <class TValue>
struct expected {
const bool Valid;
const TValue Value;
constexpr expected(bool valid, TValue value) : Valid(valid), Value(value) {}
// Implicit constructor to convert from TValue (for valid values, so an expected<T> behaves like a T)
constexpr expected(TValue validValue)
: Valid(true)
, Value(validValue)
{
}
// Implicit conversion operator to bool, so you can do things like if (myResult) { ... }
constexpr explicit operator bool() const {
return Valid;
}
// Easy default value handling
constexpr float value_or(TValue valueIfInvalid) const {
return Valid ? Value : valueIfInvalid;
}
};
constexpr expected<float> unexpected = {false, 0.0f};

View File

@ -4,19 +4,19 @@
struct AddOne final : public SensorConverter {
SensorResult convert(float input) const {
return {true, input + 1};
return input + 1;
}
};
struct SubOne final : public SensorConverter {
SensorResult convert(float input) const {
return {true, input - 1};
return input - 1;
}
};
struct Doubler final : public SensorConverter {
SensorResult convert(float input) const {
return {true, input * 2};
return input * 2;
}
};