Tuesday, December 29, 2020

Defaults with invalid value

Invalid values

In code it's often natural to have (invalid) default values for initialization and (debug) checking. For example an enum in C++:


enum Color
{
    eClrUndefined = -1,
    eClrRed       = 0,
    eClrGreen,
};

class Ball
{
    Color   m_eClr = eClrUndefined;
};

Identifier

For object identifiers a long can be used. For example:


using PersonId = long;
   
constexpr PersonId g_idInvalid = -1;

Code can test for validity of the id and checking against  an invalid value:


const PersonId id = LookupPersonId(...);

if (id != g_idInvalid)
{
   //...
}

Alternative ways of signaling invalid values are e.g. std::optional but reserving a special value is more compact.

Double

For doubles it would be natural to use a NaN as invalid default value since NaN's stay invalid when used in (accidental) calculations. Suppose:


#include <limits>

using Distance = double;

constexpr Distance g_dInvalid = std::numeric_limits<Distance>::signaling_NaN();

Checking against invalid becomes a hindrance now since NaN's never check equal against another NaN or any other number. This gives already issues when defining the equality operator which could be solved by adding an extra case for NaN:


#include <cmath>
#include <limits>

class Quantity
{
   bool operator==(const Quantity& rRhs) const noexcept
   {
      if (std::isnan(m_dValue))
      {
         return std::isnan(rRhs.m_dValue);
      }
      else
      {
         return m_dValue == rRhs.m_dValue;
      }
    }
    
    double m_dValue = std::numeric_limits<double>::signaling_NaN();
};

Alternatives might therefore be more appropriate:

  • max or an other unreachable value
  • std::optional
  • use a function e.g. IsInvalidDistance which uses isnan.

Note that exact equality checking of floating point numbers is room for another topic.

No comments:

Post a Comment

Careful with std::ranges

<ranges>   C++20 has added the the ranges library. Basically it works on ranges instead of iterators but added some subtle constraint...