core: Use std::optional to return an optional value

This commit is contained in:
Stefano Avallone
2022-05-14 08:45:04 -07:00
committed by Tom Henderson
parent cc68be51b3
commit ca59097075
3 changed files with 29 additions and 52 deletions

View File

@@ -32,7 +32,6 @@
#include <ratio> #include <ratio>
#include <sstream> #include <sstream>
#include <string> #include <string>
#include <tuple>
#include <type_traits> #include <type_traits>
#include <unordered_map> #include <unordered_map>
#include <vector> #include <vector>
@@ -235,24 +234,19 @@ NS_LOG_COMPONENT_DEFINE ("Length");
// Implement the attribute helper // Implement the attribute helper
ATTRIBUTE_HELPER_CPP (Length); ATTRIBUTE_HELPER_CPP (Length);
std::tuple<bool, Length> std::optional<Length>
Length::TryParse (double value, const std::string& unitString) Length::TryParse (double value, const std::string& unitString)
{ {
NS_LOG_FUNCTION (value << unitString); NS_LOG_FUNCTION (value << unitString);
bool validUnit = false; auto unit = FromString (unitString);
Length::Unit unit;
std::tie (validUnit, unit) = FromString (unitString); if (unit.has_value ())
Length length;
if (validUnit)
{ {
length = Length (value, unit); return Length (value, *unit);
} }
return std::make_tuple (validUnit, length); return std::nullopt;
} }
Length::Length () Length::Length ()
@@ -276,19 +270,16 @@ Length::Length (double value, const std::string& unitString)
{ {
NS_LOG_FUNCTION (this << value << unitString); NS_LOG_FUNCTION (this << value << unitString);
bool validUnit; auto unit = FromString (unitString);
Length::Unit unit;
std::tie (validUnit, unit) = FromString (unitString); if (!unit.has_value ())
if (!validUnit)
{ {
NS_FATAL_ERROR ("A Length object could not be constructed from the unit " NS_FATAL_ERROR ("A Length object could not be constructed from the unit "
"string '" << unitString << "', because the string is not associated " "string '" << unitString << "', because the string is not associated "
"with a Length::Unit entry"); "with a Length::Unit entry");
} }
m_value = Convert (value, unit, Length::Unit::Meter); m_value = Convert (value, *unit, Length::Unit::Meter);
} }
Length::Length (double value, Length::Unit unit) Length::Length (double value, Length::Unit unit)
@@ -577,7 +568,7 @@ ToName (Length::Unit unit, bool plural /*=false*/)
return std::get<0> (iter->second); return std::get<0> (iter->second);
} }
std::tuple<bool, Length::Unit> std::optional<Length::Unit>
FromString (std::string unitString) FromString (std::string unitString)
{ {
using UnitTable = std::unordered_map<std::string, Length::Unit>; using UnitTable = std::unordered_map<std::string, Length::Unit>;
@@ -654,16 +645,12 @@ FromString (std::string unitString)
auto iter = UNITS.find (unitString); auto iter = UNITS.find (unitString);
bool valid = false;
Length::Unit unit;
if (iter != UNITS.end ()) if (iter != UNITS.end ())
{ {
valid = true; return iter->second;
unit = iter->second;
} }
return std::make_tuple (valid, unit); return std::nullopt;
} }
std::ostream& std::ostream&

View File

@@ -31,9 +31,9 @@
#include <istream> #include <istream>
#include <limits> #include <limits>
#include <optional>
#include <ostream> #include <ostream>
#include <string> #include <string>
#include <tuple>
/** /**
* \file * \file
@@ -161,7 +161,7 @@ namespace ns3 {
* Addition is between two Length instances * Addition is between two Length instances
* *
* \code * \code
* std::cout << Length(1, Length::Unit::Meter) + Length (2, Length::Unit::Meter); * std::cout << Length(1, Length::Unit::Meter) + Length (2, Length::Unit::Meter);
* // output: "3 m" * // output: "3 m"
* \endcode * \endcode
* *
@@ -170,7 +170,7 @@ namespace ns3 {
* Subtraction is between two Length instances * Subtraction is between two Length instances
* *
* \code * \code
* std::cout << Length(3, Length::Unit::Meter) - Length (2, Length::Unit::Meter); * std::cout << Length(3, Length::Unit::Meter) - Length (2, Length::Unit::Meter);
* // output: "1 m" * // output: "1 m"
* \endcode * \endcode
* *
@@ -234,8 +234,8 @@ namespace ns3 {
* \code * \code
* Length m(5, Length::Unit::Meter); * Length m(5, Length::Unit::Meter);
* *
* std::cout << m << ", " * std::cout << m << ", "
* << m.As(Length::Unit::Kilometer) << ", " * << m.As(Length::Unit::Kilometer) << ", "
* << m.As(Length::Unit::Foot); * << m.As(Length::Unit::Foot);
* //output: 5 m, 0.005 km, 16.4042 ft * //output: 5 m, 0.005 km, 16.4042 ft
* \endcode * \endcode
@@ -356,12 +356,11 @@ private:
* \param value Numeric value of the new length * \param value Numeric value of the new length
* \param unit Unit that the value represents * \param unit Unit that the value represents
* *
* \return A tuple containing the success or failure of the parsing and a Length * \return A std::optional object containing the Length object constructed from
* object. If the boolean element is true, then the Length element contains the * the given value and unit, if the attempt to construct the Length object was
* parsed result. If the boolean element is false, the value of the Length * successful.
* element is undefined.
*/ */
static std::tuple<bool, Length> TryParse (double value, const std::string& unit); static std::optional<Length> TryParse (double value, const std::string& unit);
/** /**
* Default Constructor * Default Constructor
@@ -667,12 +666,10 @@ std::string ToName (Length::Unit unit, bool plural = false);
* *
* \param unitString String containing the symbol or name of a length unit * \param unitString String containing the symbol or name of a length unit
* *
* \return A tuple containing a boolean and a Length::Unit. When the boolean * \return A std::optional object containing a Length::Unit if a match for the
* is true, the Length::Unit contains a valid value. When the boolean is false, * string could be found
* a match for the string could not be found and the Length::Unit value is
* undefined
*/ */
std::tuple<bool, Length::Unit> FromString (std::string unitString); std::optional<Length::Unit> FromString (std::string unitString);
/** /**
* \ingroup length * \ingroup length

View File

@@ -39,7 +39,6 @@
#include <map> #include <map>
#include <sstream> #include <sstream>
#include <string> #include <string>
#include <tuple>
/** /**
* \file * \file
@@ -443,7 +442,7 @@ LengthTestCase::TestConstructLengthFromMeterString ()
{ {
const double value = 5; const double value = 5;
TestConstructLengthFromString (value, value, 0, TestConstructLengthFromString (value, value, 0,
{"m", "meter", "meters", "metre", "metres"}); {"m", "meter", "meters", "metre", "metres"});
} }
@@ -651,12 +650,9 @@ LengthTestCase::TestBuilderFreeFunctions ()
void void
LengthTestCase::TestTryParseReturnsFalse () LengthTestCase::TestTryParseReturnsFalse ()
{ {
bool result; auto l = Length::TryParse (1, "");
Length l;
std::tie (result, l) = Length::TryParse (1, ""); AssertFalse (l.has_value (), "TryParse returned true on bad input");
AssertFalse (result, "TryParse returned true on bad input");
} }
void void
@@ -676,18 +672,15 @@ LengthTestCase::TestTryParseReturnsTrue ()
TestInput input = entry.first; TestInput input = entry.first;
TestArgs args = entry.second; TestArgs args = entry.second;
bool result; auto l = Length::TryParse (input.first, input.second);
Length l;
std::tie (result, l) = Length::TryParse (input.first, input.second); AssertTrue (l.has_value (), "TryParse returned false when expecting true");
AssertTrue (result, "TryParse returned false when expecting true");
std::stringstream stream; std::stringstream stream;
stream << "Parsing input (" << input.first << ", " << input.second stream << "Parsing input (" << input.first << ", " << input.second
<< ") returned the wrong value"; << ") returned the wrong value";
NS_TEST_ASSERT_MSG_EQ_TOL (l.GetDouble (), args.first, args.second, stream.str ()); NS_TEST_ASSERT_MSG_EQ_TOL (l->GetDouble (), args.first, args.second, stream.str ());
} }
} }