add expected helper class (#1321)
Co-authored-by: Matthew Kennedy <makenne@microsoft.com>
This commit is contained in:
parent
c5a0da2db7
commit
7f60384c75
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -41,7 +41,7 @@ public:
|
|||
return {false, value};
|
||||
}
|
||||
|
||||
return {true, value};
|
||||
return value;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
|
|
@ -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};
|
|
@ -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;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue