error_code example 2

// This program illustrates how one can use error codes effectively:
// define a number of error code ranges from different sub-systems
// (FlightsErrc, Flights2Errc, SeatsErrc),
// define a default error condition for plugging all those codes
// into the system of errors (SubsystemError),
// and a number of 'queries' on the error codes
// (FailureSource, Severity) 
  
  
// FILE: flights.h
  
# include <system_error>
  
enum class FlightsErrc
{
  // no 0
  NonexistentLocations = 10, // requested airport doesn't exist
  DatesInThePast,            // booking flight for yesterday
  InvertedDates,             // returning before departure
  NoFlightsFound       = 20, // did not find any combination
  ProtocolViolation    = 30, // e.g., bad XML
  ConnectionError,           // could not connect to server
  ResourceError,             // service run short of resources
  Timeout,                   // did not respond in time
};
  
namespace std
{
  template <>
    struct is_error_code_enum<FlightsErrc> : true_type {};
}
  
std::error_code make_error_code(FlightsErrc);
  
// FILE: flights2.h
  
# include <system_error>
  
enum class Flights2Errc
{
  ZeroFlightsFound     = 11,
  InvalidRequestFormat = 12,
  CouldNotConnect      = 13,
  DatabaseError        = 14,
  NotEnoughMemory      = 15,
  InternalError        = 16,
  NoSuchAirport        = 17,
  JourneyInThePast     = 18,
  DatesNotMonotonic    = 19,
};
  
namespace std
{
  template <>
    struct is_error_code_enum<Flights2Errc> : true_type {};
}
  
std::error_code make_error_code(Flights2Errc);
  
// FILE: seats.h
 
enum class SeatsErrc
{
  // no 0
  InvalidRequest = 1,    // e.g., bad XML
  CouldNotConnect,       // could not connect to server
  InternalError,         // service run short of resources
  NoResponse,            // did not respond in time
  NonexistentClass,      // requested class does not exist
  NoSeatAvailable,       // all seats booked
};
 
namespace std
{
  template <>
    struct is_error_code_enum<SeatsErrc> : true_type {};
}
  
std::error_code make_error_code(SeatsErrc);


// FILE submodule_error.h

# include <system_error>

enum class SubsystemError
{
    // no 0
    InputBadAirport = 1,
    InputPastDate,
    InputBadDateRange,
    InputBadClass,
    NoFlightFound,
    NoSeatFound,
    SubsysProtocolErr,
    SubsysInternal,
    SubsysResource,
    SubsysConfig,
    SubsysTimeout,
};

namespace std
{
  template <>
    struct is_error_condition_enum<SubsystemError> : true_type {};
}
 
std::error_condition make_error_condition(SubsystemError e);


// FILE queries.h

# include <system_error>

enum class FailureSource
{
  // no 0
  BadUserInput = 1,
  SystemError = 2,
  NoSolution = 3,
};
 
namespace std
{
  template <>
    struct is_error_condition_enum<FailureSource> : true_type {};
}
 
std::error_condition make_error_condition(FailureSource e);

enum class Severity
{
  // no 0
  Bug = 1,
  Config,
  Resource,
  Normal,
};
 
namespace std
{
  template <>
    struct is_error_condition_enum<Severity> : true_type {};
}
 
std::error_condition make_error_condition(Severity e);

// FILE: main.cpp
  
// # include "flights.h"
// # include "seats.h"
# include <cassert>
# include <iostream>
  
int main ()
{
  std::error_code ec = FlightsErrc::NoFlightsFound;   
  assert (ec == SubsystemError::NoFlightFound);
  assert (ec != SubsystemError::InputBadClass);
  assert (ec == FailureSource::NoSolution);
  assert (ec != FailureSource::BadUserInput);
  assert (ec == Severity::Normal);
  assert (ec != Severity::Bug);
     
  ec = SeatsErrc::NonexistentClass;
  assert (ec != SubsystemError::NoFlightFound);
  assert (ec == SubsystemError::InputBadClass);
  assert (ec != FailureSource::NoSolution);
  assert (ec == FailureSource::BadUserInput);
  assert (ec == Severity::Normal);
  assert (ec != Severity::Config);
     
  std::cout << ec << std::endl;

  // the following illustrates how you insert
  //   raw int values into error_code system:
  int ret_value = 20; // it was returned from Flights
  std::error_code ec2 = static_cast<FlightsErrc>(ret_value);
  std::cout << ec2 << std::endl;
}
  
  
// FILE: flights.cpp
  
// # include "flights.h"
  
namespace { // anonymous namespace
   
struct FlightsErrCategory : std::error_category
{
  const char* name() const noexcept override;
  std::string message(int ev) const override;
  std::error_condition default_error_condition(int ev) const noexcept override;
};
   
const char* FlightsErrCategory::name() const noexcept
{
  return "flights";
}
   
std::string FlightsErrCategory::message(int ev) const
{
  switch (static_cast<FlightsErrc>(ev))
  {
  case FlightsErrc::NonexistentLocations:
    return "nonexistent airport name in request";
    
  case FlightsErrc::DatesInThePast:
    return "request for a date from the past";
   
  case FlightsErrc::InvertedDates:
    return "requested flight return date before departure date";
   
  case FlightsErrc::NoFlightsFound:
    return "no filight combination found";
   
  case FlightsErrc::ProtocolViolation:
    return "received malformed request";
   
  case FlightsErrc::ConnectionError:
    return "could not connect to server";
   
  case FlightsErrc::ResourceError:
    return "insufficient resources";
   
  case FlightsErrc::Timeout:
    return "processing timed out";
   
  default:
    return "(unrecognized error)";
  }
}

std::error_condition FlightsErrCategory::default_error_condition(int ev) const noexcept
{
  switch (static_cast<FlightsErrc>(ev))
  {
  case FlightsErrc::NonexistentLocations:
    return SubsystemError::InputBadAirport;
  
  case FlightsErrc::DatesInThePast:
    return SubsystemError::InputPastDate;
      
  case FlightsErrc::InvertedDates:
    return SubsystemError::InputBadDateRange;
        
  case FlightsErrc::NoFlightsFound:
    return SubsystemError::NoFlightFound;
      
  case FlightsErrc::ProtocolViolation:
    return SubsystemError::SubsysProtocolErr;
      
  case FlightsErrc::ConnectionError:
    return SubsystemError::SubsysConfig;
       
  case FlightsErrc::ResourceError:
    return SubsystemError::SubsysResource;
      
  case FlightsErrc::Timeout:
    return SubsystemError::SubsysTimeout;    

  default:
    assert(false);
    return {};
  }
}
   
const FlightsErrCategory theFlightsErrCategory {};
   
} // anonymous namespace
  
std::error_code make_error_code(FlightsErrc e)
{
  return {static_cast<int>(e), theFlightsErrCategory};
}
 
 
   
  
// FILE: flights2.cpp
  
// # include "flights2.h"
  
namespace { // anonymous namespace
   
struct Flights2ErrCategory : std::error_category
{
  const char* name() const noexcept override;
  std::string message(int ev) const override;
  std::error_condition default_error_condition(int ev) const noexcept override;
};
   
const char* Flights2ErrCategory::name() const noexcept
{
  return "flights2";
}
   
std::string Flights2ErrCategory::message(int ev) const
{
  switch (static_cast<Flights2Errc>(ev))
  {
  // return name for each enum
  default:
    return "(unrecognized error)";
  }
}

std::error_condition Flights2ErrCategory::default_error_condition(int ev) const noexcept
{
  switch (static_cast<Flights2Errc>(ev))
  {
  case Flights2Errc::ZeroFlightsFound:
    return SubsystemError::NoFlightFound;
    
  case Flights2Errc::InvalidRequestFormat:
    return SubsystemError::SubsysProtocolErr;
      
  case Flights2Errc::CouldNotConnect:
    return SubsystemError::SubsysConfig;
      
  case Flights2Errc::DatabaseError:
    return SubsystemError::SubsysInternal;
      
  case Flights2Errc::NotEnoughMemory:
    return SubsystemError::SubsysResource;
      
  case Flights2Errc::InternalError:
    return SubsystemError::SubsysInternal;
      
  case Flights2Errc::NoSuchAirport:
    return SubsystemError::InputBadAirport;
      
  case Flights2Errc::JourneyInThePast:
    return SubsystemError::InputPastDate;
      
  case Flights2Errc::DatesNotMonotonic:
    return SubsystemError::InputBadDateRange;
    
  default:
    assert(false);
    return {};
  }
}
   
const Flights2ErrCategory theFlights2ErrCategory {};
   
} // anonymous namespace
  
std::error_code make_error_code(Flights2Errc e)
{
  return {static_cast<int>(e), theFlights2ErrCategory};
}


// FILE: seats.cpp
  
// # include "seats.h"
  
namespace { // anonymous namespace
   
struct SeatsErrCategory : std::error_category
{
  const char* name() const noexcept override;
  std::string message(int ev) const override;
  std::error_condition default_error_condition(int ev) const noexcept override;
};
   
const char* SeatsErrCategory::name() const noexcept
{
  return "seats";
}
   
std::string SeatsErrCategory::message(int ev) const
{
  switch (static_cast<SeatsErrc>(ev))
  {      
  case SeatsErrc::InvalidRequest:
    return "received malformed request";
  
  case SeatsErrc::CouldNotConnect:
    return "could not connect to server";
     
  case SeatsErrc::InternalError:
    return "insufficient resources";
     
  case SeatsErrc::NoResponse:
    return "processing timed out";
           
  case SeatsErrc::NonexistentClass:
    return "requested class does not exist";
    
  case SeatsErrc::NoSeatAvailable:
    return "all seats booked";
   
  default:
    return "(unrecognized error)";
  }
}

std::error_condition SeatsErrCategory::default_error_condition(int ev) const noexcept
{
  switch (static_cast<SeatsErrc>(ev))
  {
    case SeatsErrc::InvalidRequest:
      return SubsystemError::SubsysProtocolErr;
    
    case SeatsErrc::CouldNotConnect:
      return SubsystemError::SubsysConfig;
      
    case SeatsErrc::InternalError:
      return SubsystemError::SubsysInternal;
      
    case SeatsErrc::NoResponse:
      return SubsystemError::SubsysTimeout;
      
    case SeatsErrc::NonexistentClass:
      return SubsystemError::InputBadClass;
      
    case SeatsErrc::NoSeatAvailable:
      return SubsystemError::NoSeatFound;
    
    default:
      assert(false);
      return {};
  }
}
   
const SeatsErrCategory theSeatsErrCategory {};
   
} // anonymous namespace
  
std::error_code make_error_code(SeatsErrc e)
{
  return {static_cast<int>(e), theSeatsErrCategory};
}
 
// FILE: queries.cpp
 
// # include "queries.h"
 
namespace {

class SubsystemErrorCategory : public std::error_category
{
public:
  const char* name() const noexcept override;
  std::string message(int ev) const override;
};
    
const char* SubsystemErrorCategory::name() const noexcept
{
    return "submodule-error";
}
     
std::string SubsystemErrorCategory::message(int ev) const
{
  switch (static_cast<SubsystemError>(ev))
  {
      default:
          return "(uncharted)";
  }
}

const SubsystemErrorCategory theSubsystemErrorCategory {};


}


std::error_condition make_error_condition(SubsystemError e)
{
  return {static_cast<int>(e), theSubsystemErrorCategory};
}

// -----------------

namespace {
class FailureSourceCategory : public std::error_category
{
public:
  const char* name() const noexcept override;
  std::string message(int ev) const override;
  bool equivalent(
      const std::error_code& code,
      int condition) const noexcept override;
};
     
const char* FailureSourceCategory::name() const noexcept
{
    return "failure-source";
}
     
std::string FailureSourceCategory::message(int ev) const
{
  switch (static_cast<FailureSource>(ev))
  {
  case FailureSource::BadUserInput:
    return "invalid user request";
    
  case FailureSource::SystemError:
    return "internal error";
   
  case FailureSource::NoSolution:
    return "no solution found for specified request";
   
  default:
    return "(unrecognized condition)";
  }
}
     
bool FailureSourceCategory::equivalent(
      const std::error_code& ec,
      int cond) const noexcept
{     
  switch (static_cast<FailureSource>(cond))
  {
  case FailureSource::BadUserInput:
    return ec == SubsystemError::InputBadAirport
        || ec == SubsystemError::InputPastDate
        || ec == SubsystemError::InputBadDateRange
        || ec == SubsystemError::InputBadClass;

  case FailureSource::SystemError:
    return ec == SubsystemError::SubsysProtocolErr
        || ec == SubsystemError::SubsysInternal
        || ec == SubsystemError::SubsysResource
        || ec == SubsystemError::SubsysConfig        
        || ec == SubsystemError::SubsysTimeout;
        
  case FailureSource::NoSolution:
    return ec == SubsystemError::NoFlightFound
        || ec == SubsystemError::NoSeatFound;
             
  default:
    return false;
  }
}
     
const FailureSourceCategory theFailureSourceCategory {};
   
} // anonymous namespace
  
std::error_condition make_error_condition(FailureSource e)
{
  return {static_cast<int>(e), theFailureSourceCategory};
}

// --------------
namespace {
class SeverityCategory : public std::error_category
{
public:
  const char* name() const noexcept override;
  std::string message(int ev) const override;
  bool equivalent(
      const std::error_code& code,
      int condition) const noexcept override;
};
     
const char* SeverityCategory::name() const noexcept
{
    return "severity";
}
     
std::string SeverityCategory::message(int ev) const
{
  switch (static_cast<Severity>(ev))
  {
  case Severity::Bug:
    return "failure is a programmer bug";
    
  case Severity::Config:
    return "failure is a configuration error";
    
  case Severity::Resource:
    return "failure is caused by resource shortage";
  
  case Severity::Normal:
    return "failure requires no attention";  
  
  default:
    return "(unrecognized condition)";
  }
}
     
bool SeverityCategory::equivalent(
      const std::error_code& ec,
      int cond) const noexcept
{     
  switch (static_cast<Severity>(cond))
  {
  case Severity::Bug:
    return ec == SubsystemError::SubsysProtocolErr
        || ec == SubsystemError::SubsysInternal;
        
  case Severity::Config:
    return ec == SubsystemError::SubsysConfig;

  case Severity::Resource:
    return ec == SubsystemError::SubsysResource        
        || ec == SubsystemError::SubsysTimeout;
        
  case Severity::Normal:
    return ec == SubsystemError::InputBadAirport
        || ec == SubsystemError::InputPastDate
        || ec == SubsystemError::InputBadDateRange
        || ec == SubsystemError::InputBadClass
        || ec == SubsystemError::NoFlightFound
        || ec == SubsystemError::NoSeatFound;
             
  default:
    return false;
  }
}
     
const SeverityCategory theSeverityCategory {};
   
} // anonymous namespace
  
std::error_condition make_error_condition(Severity e)
{
  return {static_cast<int>(e), theSeverityCategory};
}