mirror of
https://gitlab.com/fbb-git/cppannotations
synced 2024-09-28 03:20:44 +02:00
completed the system_error description in advancedtemplates
This commit is contained in:
parent
8b41d305a2
commit
0a5dc51fc2
76 changed files with 213 additions and 189 deletions
|
@ -15,7 +15,7 @@ associations are collected in a class template tt(CatMap), derived from
|
|||
tt(std::unordered_map). tt(CatMap)'s design is a rather straightforward,
|
||||
offering a constructor accepting an tt(std::initializer_list):
|
||||
|
||||
verbinsert(-s4 //impl examples/errcode2/catmap/catmap.h)
|
||||
verbinsert(-s4 //impl examples/errcode/catmap/catmap.h)
|
||||
|
||||
As tt(ErrorCodeEnum)-values may have been randomly assigned (not using 0)
|
||||
tt(CapMap) objects offers fast access to the errors' descriptions and
|
||||
|
@ -40,7 +40,7 @@ const) member, returning the description matching tt(ev) or the error message
|
|||
tt(noEnumValue) if tt(ev) does not represent a defined enum value. Here is its
|
||||
implementation:
|
||||
|
||||
verbinsert(-s4 //msg examples/errcode2/categorybase/categorybase.h)
|
||||
verbinsert(-s4 //msg examples/errcode/categorybase/categorybase.h)
|
||||
|
||||
But that isn't all that tt(CategoryBase) can accomplish: since it contains
|
||||
tt(s_errors), the associations between error enum values and category
|
||||
|
@ -59,7 +59,7 @@ tt(s_errors), and compares the stored error condition's name to the name
|
|||
provided by the (singleton) tt(error_condition) object, given the condition's
|
||||
number. Here is its implementation:
|
||||
|
||||
verbinsert(-s4 //equiv examples/errcode2/categorybase/categorybase.h)
|
||||
verbinsert(-s4 //equiv examples/errcode/categorybase/categorybase.h)
|
||||
|
||||
In addition, to allow single inheritance to be used when deriving classes from
|
||||
tt(std::error_category) the class tt(CategoryBase) itself is derived from
|
||||
|
@ -71,7 +71,7 @@ tt(equivalent) that can be used by all classes derived from
|
|||
tt(std::error_category); and, finally, a class that itself also is an
|
||||
tt(error_category) class. Here is the interface of tt(CategoryBase):
|
||||
|
||||
verbinsert(-s4 //impl examples/errcode2/categorybase/categorybase.h)
|
||||
verbinsert(-s4 //impl examples/errcode/categorybase/categorybase.h)
|
||||
|
||||
Now we're ready for defining our own error category classes. To define a
|
||||
category class we take the following steps:
|
||||
|
@ -86,12 +86,12 @@ category class we take the following steps:
|
|||
tt(CalculatorCategory's) class interface:
|
||||
|
||||
verbinsert(//class
|
||||
examples/errcode2/calculatorcategory/calculatorcategory.h)
|
||||
examples/errcode/calculatorcategory/calculatorcategory.h)
|
||||
|
||||
The member tt(instance) returns a reference to the singleton object,
|
||||
initializing it the first time it is called:
|
||||
|
||||
verbinsert(//impl examples/errcode2/calculatorcategory/instance.cc)
|
||||
verbinsert(//impl examples/errcode/calculatorcategory/instance.cc)
|
||||
|
||||
it() The member tt(name) simply returns a short string naming the category
|
||||
(tt("calculator") for the calculator category).
|
||||
|
@ -100,7 +100,7 @@ category class we take the following steps:
|
|||
thanks to tt(CategoryBase::member): it merely returns what's returned by
|
||||
that latter member:
|
||||
|
||||
verbinsert(//impl examples/errcode2/calculatorcategory/messace.cc)
|
||||
verbinsert(//impl examples/errcode/calculatorcategory/messace.cc)
|
||||
|
||||
it() The associations between error code enum values, descriptions and
|
||||
error condition names are defined when initializing the tt(CatMap)
|
||||
|
@ -108,20 +108,20 @@ category class we take the following steps:
|
|||
base class it can be initialized when defining the category
|
||||
class. Here is the initialization for tt(CalculatorCategory):
|
||||
|
||||
verbinsert(//impl examples/errcode2/calculatorcategory/data.cc)
|
||||
verbinsert(//impl examples/errcode/calculatorcategory/data.cc)
|
||||
|
||||
it() We're now in position to actually create tt(error_code) objects from
|
||||
tt(CalculatorError) enum values. For this we define the free function
|
||||
tt(make_error_code(CalculatorError ce)):
|
||||
|
||||
verbinsert(//impl examples/errcode2/calculatorcategory/makeerrorcode.cc)
|
||||
verbinsert(//impl examples/errcode/calculatorcategory/makeerrorcode.cc)
|
||||
)
|
||||
|
||||
Now that a tt(CalculatorError) value can be converted to an
|
||||
tt(std::error_code) we can use it in our programs. Here is a little demo
|
||||
program illustrating its use:
|
||||
|
||||
verbinsert(-as4 examples/errcode2/main.part);
|
||||
verbinsert(-as4 examples/errcode/main.part);
|
||||
|
||||
In the next section defining and using error conditions is covered in detail.
|
||||
|
||||
|
|
|
@ -44,8 +44,8 @@ itemization(
|
|||
it() Our first step consists of defining our own error enumerations: one
|
||||
related to the calculator and one related to the simulator:
|
||||
|
||||
verbinsert(//enum examples/errcode2/calculatorerror/calculatorerror.h)
|
||||
verbinsert(//enum examples/errcode2/simulatorerror/simulatorerror.h)
|
||||
verbinsert(//enum examples/errcode/calculatorerror/calculatorerror.h)
|
||||
verbinsert(//enum examples/errcode/simulatorerror/simulatorerror.h)
|
||||
|
||||
The class tt(std::error_code) is designed so that two pieces of
|
||||
information (the error value and its category) become available. The
|
||||
|
@ -80,7 +80,7 @@ it() Second, our intention is to let tt(error_code) accept
|
|||
Here is the specialization for tt(CalculatorError); the one for
|
||||
tt(SimulatorError) is defined analogously:
|
||||
|
||||
verbinsert(//trait examples/errcode2/calculatorerror/.h)
|
||||
verbinsert(//trait examples/errcode/calculatorerror/.h)
|
||||
|
||||
This completes the definition of our own error enumerations, which are
|
||||
now `promoted' to tt(ErrorCodeEnums).
|
||||
|
|
|
@ -32,58 +32,68 @@ instead use verbal labels denoting error conditions. So rather than specifying
|
|||
};
|
||||
)
|
||||
textual labels like tt("InputCond", "UnavailCond",) and tt("SystemCond")
|
||||
could be used. Instead of defining a fixed-size tt(enum class ErrorCondition)
|
||||
a singleton tt(class ErrorCondition) is defined, guaranteeing the uniqueness
|
||||
of error conditions which are identified by their textual labels.
|
||||
could be used. Instead of defining a fixed-size tt(ErrorConditionEnum) a
|
||||
singleton class tt(ErrorCondition) is used, providing and encapsulating such
|
||||
an enumeration, at the same time guaranteeing the uniqueness of error
|
||||
conditions which are identified by textual labels.
|
||||
|
||||
Error conditions are obtained from a function tt(make_error_condition),
|
||||
expecting an tt(ErrorConditionEnum) value as its argument, and using an
|
||||
tt(std::error_category) that is associated with
|
||||
the various error condition enum values, much like tt(CalculatorCategory) was
|
||||
associated with the tt(CalculatorError) enumeration. The tt(std::error_category)
|
||||
The class tt(ConditionCategory) implements the requirements imposed by the
|
||||
class tt(std::error_condition), tailored to the error conditions managed by
|
||||
the class tt(ErrorCondition). Also designed as a singleton,
|
||||
tt(ConditionCategory) contains a vector whose elements hold names and
|
||||
descriptions of the various error conditions. In addition to the familiar
|
||||
members tt(name, message) and tt(equivalent) it offers a member
|
||||
tt(addCondition). That latter function is used by tt(ErrorCondition) to add
|
||||
new error conditions to the current set. Here is its interface:
|
||||
verbinsert(-s4 //class
|
||||
examples/errcode/conditioncategory/conditioncategory.h)
|
||||
|
||||
========================== WIP
|
||||
The members tt(name) and tt(message) have trivial implementations. The member
|
||||
tt(equivalent) receives an tt(error_code) object and an error condition enum
|
||||
value (as an tt(int)). The function must return tt(true) if the provided
|
||||
tt(error_code) is associated with the provided error condition enum
|
||||
value. tt(Equivalent) itself doesn't perform those checks. Rather, it
|
||||
retrieves the tt(error_code's error_category) and uses that object's
|
||||
tt(equivalent) function to perform the test:
|
||||
verbinsert(-s4 //impl
|
||||
examples/errcode/conditioncategory/equivalent.cc)
|
||||
|
||||
Next we look at the class tt(ErrorCondition). It contains a
|
||||
tt(ConditionCategory) object (i.e., em(the) tt(ConditionCategory) object), and
|
||||
a tt(unsorted_map), mapping condition names to their indices in the
|
||||
tt(ConditionCategory's) vector. Other than that it's a rather plain class,
|
||||
offering members to retrieve the enum values of the various error conditions,
|
||||
and returning conditions' names given their numbers. Error condition enum
|
||||
values are simply defined as their indices in the tt(ConditionCategory's)
|
||||
vector, statically cast to the enum tt(ErrorCondition::Enum).
|
||||
|
||||
tt(Enum) by itself is defined as mere enumeration name, promoted to an
|
||||
tt(ErrorConditionEnum) by the tt(std::is_error_condition_enum) trait class
|
||||
specialization (comparable to what the tt(is_error_code_enum) trait class
|
||||
accomplished for our enums like tt(CalculatorError)). Here is the
|
||||
tt(is_error_condition_enum) trait class specialization, followed by
|
||||
tt(ErrorCondition's) class interface:
|
||||
verbinsert(-s4 //trait examples/errcode/errorcondition/errorcondition.h)
|
||||
|
||||
is provided by an object of the class tt(ErrorCondCat)
|
||||
. To create an tt(error_condition) an tt(ErrorCondition::Enum) value
|
||||
is required and the enum's value matching error category.
|
||||
verbinsert(-s4 //class examples/errcode/errorcondition/errorcondition.h)
|
||||
|
||||
Error conditions objects themselves are returned by a function
|
||||
tt(make_error_condition), expecting an tt(ErrorConditionEnum) value as its
|
||||
argument, and internally using an tt(std::error_category) that is associated
|
||||
with the various error condition enum values, much like tt(CalculatorCategory)
|
||||
was associated with the tt(CalculatorError) enumeration. Since
|
||||
tt(ConditionCategory) is a singleton, it can directly pass that singleton
|
||||
object to the tt(std::error_condition) object:
|
||||
|
||||
verbinsert(-s4 //make
|
||||
examples/errcode/errorcondition/makeerrorcondition.cc)
|
||||
|
||||
A demo program illustrating some of the facilities of the tt(error_code,
|
||||
error_category, error_condition) and related classes concludes this
|
||||
section. The complete implementation of the program is provided in the
|
||||
annotations()' source archive in the directory
|
||||
tt(yo/advancedtemplates/examples/errocde).
|
||||
|
||||
: their uniqueness can be guaranteed by another class,
|
||||
tt(ErrorCondition), which is also a singleton. That class defines an empty
|
||||
tt(enum Enum), which is promoted to an tt(ErrorConditionEnum) by the
|
||||
tt(std::is_error_condition_enum) trait class specialization:
|
||||
verbinsert(-s4 //trait examples/errorcondition/errorcondition.h)
|
||||
verbinsert(-s4 //demo examples/errcode/errcode/main.cc)
|
||||
|
||||
Error ondition objects are created by
|
||||
|
||||
The tt(ErrorCondition) singleton also has a member tt(addCondition)
|
||||
allowing programs to add error conditions by name (and a description).
|
||||
|
||||
To access error condition objects a
|
||||
|
||||
|
||||
Let's
|
||||
define our conditions as:
|
||||
verbinsert(-s4 //simerrsrc examples/errcodeenum.cc)
|
||||
This allows us to distinguish errors made by the user, errors from the
|
||||
calculator, and errors from the simulator. As in the previous section, we'll
|
||||
`promote' this enum, this time to an ti(ErrorConditionEnum):
|
||||
verbinsert(-s4 //simcondtrait examples/errcodeenum.cc)
|
||||
|
||||
Now that an error condition enumeration has been defined, error codes can be
|
||||
mapped to their appropriate error condition values. To do that, a tt(class
|
||||
ErrorSourceCategory) is derived (again: in the anonymous namespace) from
|
||||
tt(std::error_category), similarly to what we did before with, e.g.,
|
||||
tt(CalculatorErrCategory):
|
||||
verbinsert(-s4 //errorourcecat examples/errcodeenum.cc)
|
||||
|
||||
The tt(name) and tt(message) members are defined as before, but in
|
||||
addition the member tt(equivalent) is defined comparing a received
|
||||
tt(error_code) to the available tt(SimErrSource) values. The function
|
||||
tt(equivalent) returns tt(true) if tt(error_code code) can be mapped to tt(int
|
||||
condition), which in fact is a statically cast tt(SimErrSource) value. For tt(
|
||||
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
calculatorerror
|
||||
simulatorerror
|
||||
errorsource
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
#include <system_error>
|
||||
|
||||
//enum
|
||||
//calcerrc
|
||||
enum class CalculatorError
|
||||
{
|
||||
// no 0, since that's by convention implies no error
|
||||
|
@ -16,19 +16,25 @@ enum class CalculatorError
|
|||
MissingParentheses, // ( and ) don't match
|
||||
};
|
||||
//=
|
||||
//trait
|
||||
|
||||
class CalculatorCategory: public std::error_category
|
||||
{
|
||||
char const *name() const noexcept override;
|
||||
std::string message(int ce) const override;
|
||||
};
|
||||
|
||||
extern CalculatorCategory const calculatorCategory;
|
||||
|
||||
std::error_code make_error_code(CalculatorError ce);
|
||||
|
||||
//calctrait
|
||||
namespace std
|
||||
{
|
||||
template <>
|
||||
struct is_error_code_enum<CalculatorError>: public true_type
|
||||
{};
|
||||
}
|
||||
|
||||
//=
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -1,6 +1,5 @@
|
|||
#define CLS
|
||||
#define MAIN "main.cc"
|
||||
#define LIBRARY "modules"
|
||||
#define SOURCES "*.cc"
|
||||
#define OBJ_EXT ".o"
|
||||
#define SHAREDREQ ""
|
19
annotations/yo/advancedtemplates/examples/errcode.1/main.cc
Normal file
19
annotations/yo/advancedtemplates/examples/errcode.1/main.cc
Normal file
|
@ -0,0 +1,19 @@
|
|||
#include "main.ih"
|
||||
|
||||
int main()
|
||||
try
|
||||
{
|
||||
std::error_code ec = CalculatorError::TypeError;
|
||||
assert(ec == ErrorSource::CalcError);
|
||||
assert(ec != ErrorSource::SimError);
|
||||
assert(ec != ErrorSource::InputError);
|
||||
|
||||
ec = CalculatorError::ArityError;
|
||||
std::cout << ec << ' ' << ec.message() << '\n';
|
||||
throw std::system_error{ ec, "For demonstration purposes: " };
|
||||
}
|
||||
catch (std::system_error &se)
|
||||
{
|
||||
std::cout << se.what() << ": " << se.code() << '\n';
|
||||
}
|
||||
|
11
annotations/yo/advancedtemplates/examples/errcode.1/main.ih
Normal file
11
annotations/yo/advancedtemplates/examples/errcode.1/main.ih
Normal file
|
@ -0,0 +1,11 @@
|
|||
#include <cassert>
|
||||
#include <iostream>
|
||||
// #include <string>
|
||||
// // #include <unordered_map>
|
||||
// #include <system_error>
|
||||
|
||||
#include "calculatorerror/calculatorerror.h"
|
||||
#include "simulatorerror/simulatorerror.h"
|
||||
|
||||
#include "errorsource/errorsource.h"
|
||||
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
#include <system_error>
|
||||
|
||||
//enum
|
||||
//=simerrc
|
||||
enum class SimulatorError
|
||||
{
|
||||
// no 0
|
||||
|
@ -16,6 +16,12 @@ enum class SimulatorError
|
|||
};
|
||||
//=
|
||||
|
||||
class SimulatorCategory: public std::error_category
|
||||
{
|
||||
char const *name() const noexcept override;
|
||||
std::string message(int ce) const override;
|
||||
};
|
||||
|
||||
namespace std
|
||||
{
|
||||
template <>
|
||||
|
@ -23,6 +29,10 @@ namespace std
|
|||
{};
|
||||
}
|
||||
|
||||
std::error_code make_error_code(SimulatorError ce);
|
||||
|
||||
extern SimulatorCategory const simulatorCategory;
|
||||
|
||||
#endif
|
||||
|
||||
|
|
@ -1,3 +1,8 @@
|
|||
calculatorerror
|
||||
simulatorerror
|
||||
errorsource
|
||||
// specific error categories, defined for this program
|
||||
calculatorcategory
|
||||
simulatorcategory
|
||||
|
||||
// classes handling all error conditions
|
||||
conditioncategory
|
||||
errorcondition
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
#include <system_error>
|
||||
|
||||
//calcerrc
|
||||
//enum
|
||||
enum class CalculatorError
|
||||
{
|
||||
// no 0, since that's by convention implies no error
|
||||
|
@ -16,25 +16,19 @@ enum class CalculatorError
|
|||
MissingParentheses, // ( and ) don't match
|
||||
};
|
||||
//=
|
||||
|
||||
class CalculatorCategory: public std::error_category
|
||||
{
|
||||
char const *name() const noexcept override;
|
||||
std::string message(int ce) const override;
|
||||
};
|
||||
|
||||
extern CalculatorCategory const calculatorCategory;
|
||||
|
||||
std::error_code make_error_code(CalculatorError ce);
|
||||
|
||||
//calctrait
|
||||
//trait
|
||||
namespace std
|
||||
{
|
||||
template <>
|
||||
struct is_error_code_enum<CalculatorError>: public true_type
|
||||
{};
|
||||
}
|
||||
|
||||
//=
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#include <string>
|
||||
#include <tuple>
|
||||
|
||||
//class
|
||||
class ConditionCategory: public std::error_category
|
||||
{
|
||||
static ConditionCategory *s_instance;
|
||||
|
@ -25,16 +26,18 @@ class ConditionCategory: public std::error_category
|
|||
bool equivalent(std::error_code const &code,
|
||||
int condition) const noexcept override;
|
||||
|
||||
// returns condition idx-th name
|
||||
std::string const &operator[](size_t idx) const;
|
||||
void addCondition(char const *name, char const *description);
|
||||
size_t size() const;
|
||||
std::string const &operator[](size_t idx) const;
|
||||
|
||||
private:
|
||||
ConditionCategory();
|
||||
};
|
||||
//=
|
||||
|
||||
inline void ConditionCategory::addCondition(char const *name,
|
||||
char const *description)
|
||||
char const *description)
|
||||
{
|
||||
d_conditionInfo.push_back({ name, description });
|
||||
}
|
||||
|
@ -50,6 +53,3 @@ inline std::string const &ConditionCategory::operator[](size_t idx) const
|
|||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
|
@ -5,9 +5,10 @@
|
|||
// error code and the condition number to verify that the error condition
|
||||
// associated with the error_code matches the condition number.
|
||||
|
||||
|
||||
//impl
|
||||
bool ConditionCategory::equivalent(std::error_code const &ec, int condNr )
|
||||
const noexcept
|
||||
{
|
||||
return ec.category().equivalent(ec, condNr);
|
||||
}
|
||||
//=
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
#include "../conditioncategory/conditioncategory.h"
|
||||
|
||||
//class
|
||||
class ErrorCondition
|
||||
{
|
||||
static ErrorCondition *s_instance;
|
||||
|
@ -31,8 +32,10 @@ class ErrorCondition
|
|||
private:
|
||||
ErrorCondition(); // singleton, see instance.cc
|
||||
|
||||
friend std::error_condition make_error_condition(Enum ec);
|
||||
};
|
||||
//=
|
||||
|
||||
std::error_condition make_error_condition(ErrorCondition::Enum ec);
|
||||
|
||||
inline std::string const &ErrorCondition::operator[](size_t nr) const
|
||||
{
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
std::error_condition make_error_condition(ErrorCondition::Enum ec)
|
||||
{
|
||||
return { static_cast<int>(ec), ErrorCondition::instance().d_ec };
|
||||
return { static_cast<int>(ec), ConditionCategory::instance() };
|
||||
}
|
||||
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
#define CLS
|
||||
#define MAIN "main.cc"
|
||||
#define LIBRARY "modules"
|
||||
#define SOURCES "*.cc"
|
||||
#define OBJ_EXT ".o"
|
||||
#define SHAREDREQ ""
|
||||
|
@ -9,7 +10,7 @@
|
|||
#define CXXFLAGS " --std=c++17 -Wall -O2" \
|
||||
" -fdiagnostics-color=never "
|
||||
#define IH ".ih"
|
||||
//#define PRECOMP "-x c++-header"
|
||||
#define PRECOMP "-x c++-header"
|
||||
#define REFRESH
|
||||
#define LDFLAGS ""
|
||||
#define ADD_LIBRARIES ""
|
||||
|
|
|
@ -1,19 +1,55 @@
|
|||
#include "main.ih"
|
||||
|
||||
//demo
|
||||
int main()
|
||||
try
|
||||
{
|
||||
ErrorCondition &errorCond = ErrorCondition::instance();
|
||||
|
||||
std::cerr << CalculatorCategory::instance().name() << '\n' <<
|
||||
SimulatorCategory::instance().name() << '\n';
|
||||
|
||||
errorCond.addCondition("InputCond", "error in user request");
|
||||
errorCond.addCondition("UnavailCond", "function not available");
|
||||
errorCond.addCondition("SystemCond", "system failure");
|
||||
|
||||
// ec is an actual error code, belonging to some error enum
|
||||
// the assert checks whether the specified error code belongs to
|
||||
// the specified error condition
|
||||
|
||||
// // also OK: ErrorCondition::Enum{};
|
||||
// std::error_condition cond = errorCond("InputCond");
|
||||
|
||||
std::error_code ec = CalculatorError::TypeError;
|
||||
assert(ec == ErrorSource::CalcError);
|
||||
assert(ec != ErrorSource::SimError);
|
||||
assert(ec != ErrorSource::InputError);
|
||||
|
||||
std::cerr << "Enum value of UnavailCond = " <<
|
||||
errorCond("UnavailCond") << '\n';
|
||||
assert(ec != ErrorCondition::Enum{});
|
||||
assert(ec == errorCond("UnavailCond"));
|
||||
assert(ec != errorCond("SystemCond"));
|
||||
|
||||
ec = CalculatorError::MissingParentheses;
|
||||
assert(ec == errorCond("InputCond"));
|
||||
|
||||
ec = CalculatorError::ArityError;
|
||||
std::cout << ec << ' ' << ec.message() << '\n';
|
||||
throw std::system_error{ ec, "For demonstration purposes: " };
|
||||
throw std::system_error{ ec, "For demonstration purposes" };
|
||||
}
|
||||
catch (std::system_error &se)
|
||||
catch (std::system_error const &se)
|
||||
{
|
||||
std::cout << se.what() << ": " << se.code() << '\n';
|
||||
std::cout << "System Error: " << se.what() << ":\n"
|
||||
" " << se.code() << '\n';
|
||||
//throw; cannot be rethrown!!
|
||||
}
|
||||
/*
|
||||
Produced output:
|
||||
|
||||
calculator
|
||||
simulator
|
||||
Enum value of UnavailCond = 2
|
||||
calculator:4 incorrect number of arguments
|
||||
System Error: For demonstration purposes: incorrect number of arguments:
|
||||
calculator:4
|
||||
*/
|
||||
|
||||
//=
|
||||
|
|
|
@ -1,11 +1,15 @@
|
|||
#include <cassert>
|
||||
|
||||
#include <iostream>
|
||||
// #include <string>
|
||||
// // #include <unordered_map>
|
||||
// #include <system_error>
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <system_error>
|
||||
|
||||
#include "calculatorerror/calculatorerror.h"
|
||||
#include "calculatorcategory/calculatorcategory.h"
|
||||
|
||||
#include "simulatorerror/simulatorerror.h"
|
||||
#include "simulatorcategory/simulatorcategory.h"
|
||||
|
||||
#include "errorsource/errorsource.h"
|
||||
#include "errorcondition/errorcondition.h"
|
||||
|
||||
|
|
|
@ -9,15 +9,17 @@ try
|
|||
{
|
||||
std::error_code ec = CalculatorError::ArityError;
|
||||
std::cout << ec << ' ' << ec.message() << '\n';
|
||||
throw std::system_error{ ec, "For demonstration purposes: " };
|
||||
throw std::system_error{ ec, "For demonstration purposes" };
|
||||
}
|
||||
catch (std::system_error &se)
|
||||
{
|
||||
std::cout << se.what() << ": " << se.code() << '\n';
|
||||
std::cout << se.what() << ":\n"
|
||||
" " << se.code() << '\n';
|
||||
}
|
||||
|
||||
/*
|
||||
Outputs:
|
||||
calculator:4 incorrect number of arguments
|
||||
For demonstration purposes: : incorrect number of arguments: calculator:4
|
||||
For demonstration purposes: incorrect number of arguments:
|
||||
calculator:4
|
||||
*/
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
#include <system_error>
|
||||
|
||||
//=simerrc
|
||||
//enum
|
||||
enum class SimulatorError
|
||||
{
|
||||
// no 0
|
||||
|
@ -16,12 +16,6 @@ enum class SimulatorError
|
|||
};
|
||||
//=
|
||||
|
||||
class SimulatorCategory: public std::error_category
|
||||
{
|
||||
char const *name() const noexcept override;
|
||||
std::string message(int ce) const override;
|
||||
};
|
||||
|
||||
namespace std
|
||||
{
|
||||
template <>
|
||||
|
@ -29,10 +23,6 @@ namespace std
|
|||
{};
|
||||
}
|
||||
|
||||
std::error_code make_error_code(SimulatorError ce);
|
||||
|
||||
extern SimulatorCategory const simulatorCategory;
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
|
|
@ -1,8 +0,0 @@
|
|||
// specific error categories, defined for this program
|
||||
calculatorcategory
|
||||
simulatorcategory
|
||||
|
||||
// classes handling all error conditions
|
||||
conditioncategory
|
||||
errorcondition
|
||||
|
|
@ -1,47 +0,0 @@
|
|||
#include "main.ih"
|
||||
|
||||
int main()
|
||||
try
|
||||
{
|
||||
ErrorCondition &errorCond = ErrorCondition::instance();
|
||||
|
||||
std::cerr << CalculatorCategory::instance().name() << '\n' <<
|
||||
SimulatorCategory::instance().name() << '\n';
|
||||
|
||||
errorCond.addCondition("InputCond", "error in user request");
|
||||
errorCond.addCondition("UnavailCond", "function not available");
|
||||
errorCond.addCondition("SystemCond", "system failure");
|
||||
|
||||
// ec is an actual error code, belonging to some error enum
|
||||
// the assert checks whether the specified error code belongs to
|
||||
// the specified error condition
|
||||
|
||||
// // also OK: ErrorCondition::Enum{};
|
||||
// std::error_condition cond = errorCond("InputCond");
|
||||
|
||||
std::error_code ec = CalculatorError::TypeError;
|
||||
|
||||
std::cerr << "Enum value of UnavailCond = " << errorCond("UnavailCond") <<
|
||||
'\n';
|
||||
assert(ec != ErrorCondition::Enum{});
|
||||
assert(ec == errorCond("UnavailCond"));
|
||||
assert(ec != errorCond("SystemCond"));
|
||||
|
||||
ec = CalculatorError::MissingParentheses;
|
||||
assert(ec == errorCond("InputCond"));
|
||||
|
||||
ec = CalculatorError::ArityError;
|
||||
std::cout << ec << ' ' << ec.message() << '\n';
|
||||
throw std::system_error{ ec, "For demonstration purposes: " };
|
||||
}
|
||||
catch (std::system_error const &se)
|
||||
{
|
||||
std::cout << "System Error: " << se.what() << ": " << se.code() << '\n';
|
||||
|
||||
//throw; cannot be rethrown!!
|
||||
|
||||
}
|
||||
catch (std::exception const &exc)
|
||||
{
|
||||
std::cout << "Exception: " << exc.what() << '\n';
|
||||
}
|
|
@ -1,15 +0,0 @@
|
|||
#include <cassert>
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
#include <system_error>
|
||||
|
||||
#include "calculatorerror/calculatorerror.h"
|
||||
#include "calculatorcategory/calculatorcategory.h"
|
||||
|
||||
#include "simulatorerror/simulatorerror.h"
|
||||
#include "simulatorcategory/simulatorcategory.h"
|
||||
|
||||
#include "errorcondition/errorcondition.h"
|
||||
|
Loading…
Reference in a new issue