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,
|
tt(std::unordered_map). tt(CatMap)'s design is a rather straightforward,
|
||||||
offering a constructor accepting an tt(std::initializer_list):
|
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)
|
As tt(ErrorCodeEnum)-values may have been randomly assigned (not using 0)
|
||||||
tt(CapMap) objects offers fast access to the errors' descriptions and
|
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
|
tt(noEnumValue) if tt(ev) does not represent a defined enum value. Here is its
|
||||||
implementation:
|
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
|
But that isn't all that tt(CategoryBase) can accomplish: since it contains
|
||||||
tt(s_errors), the associations between error enum values and category
|
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
|
provided by the (singleton) tt(error_condition) object, given the condition's
|
||||||
number. Here is its implementation:
|
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
|
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
|
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(std::error_category); and, finally, a class that itself also is an
|
||||||
tt(error_category) class. Here is the interface of tt(CategoryBase):
|
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
|
Now we're ready for defining our own error category classes. To define a
|
||||||
category class we take the following steps:
|
category class we take the following steps:
|
||||||
|
@ -86,12 +86,12 @@ category class we take the following steps:
|
||||||
tt(CalculatorCategory's) class interface:
|
tt(CalculatorCategory's) class interface:
|
||||||
|
|
||||||
verbinsert(//class
|
verbinsert(//class
|
||||||
examples/errcode2/calculatorcategory/calculatorcategory.h)
|
examples/errcode/calculatorcategory/calculatorcategory.h)
|
||||||
|
|
||||||
The member tt(instance) returns a reference to the singleton object,
|
The member tt(instance) returns a reference to the singleton object,
|
||||||
initializing it the first time it is called:
|
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
|
it() The member tt(name) simply returns a short string naming the category
|
||||||
(tt("calculator") for the calculator 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
|
thanks to tt(CategoryBase::member): it merely returns what's returned by
|
||||||
that latter member:
|
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
|
it() The associations between error code enum values, descriptions and
|
||||||
error condition names are defined when initializing the tt(CatMap)
|
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
|
base class it can be initialized when defining the category
|
||||||
class. Here is the initialization for tt(CalculatorCategory):
|
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
|
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(CalculatorError) enum values. For this we define the free function
|
||||||
tt(make_error_code(CalculatorError ce)):
|
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
|
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
|
tt(std::error_code) we can use it in our programs. Here is a little demo
|
||||||
program illustrating its use:
|
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.
|
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
|
it() Our first step consists of defining our own error enumerations: one
|
||||||
related to the calculator and one related to the simulator:
|
related to the calculator and one related to the simulator:
|
||||||
|
|
||||||
verbinsert(//enum examples/errcode2/calculatorerror/calculatorerror.h)
|
verbinsert(//enum examples/errcode/calculatorerror/calculatorerror.h)
|
||||||
verbinsert(//enum examples/errcode2/simulatorerror/simulatorerror.h)
|
verbinsert(//enum examples/errcode/simulatorerror/simulatorerror.h)
|
||||||
|
|
||||||
The class tt(std::error_code) is designed so that two pieces of
|
The class tt(std::error_code) is designed so that two pieces of
|
||||||
information (the error value and its category) become available. The
|
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
|
Here is the specialization for tt(CalculatorError); the one for
|
||||||
tt(SimulatorError) is defined analogously:
|
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
|
This completes the definition of our own error enumerations, which are
|
||||||
now `promoted' to tt(ErrorCodeEnums).
|
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")
|
textual labels like tt("InputCond", "UnavailCond",) and tt("SystemCond")
|
||||||
could be used. Instead of defining a fixed-size tt(enum class ErrorCondition)
|
could be used. Instead of defining a fixed-size tt(ErrorConditionEnum) a
|
||||||
a singleton tt(class ErrorCondition) is defined, guaranteeing the uniqueness
|
singleton class tt(ErrorCondition) is used, providing and encapsulating such
|
||||||
of error conditions which are identified by their textual labels.
|
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),
|
The class tt(ConditionCategory) implements the requirements imposed by the
|
||||||
expecting an tt(ErrorConditionEnum) value as its argument, and using an
|
class tt(std::error_condition), tailored to the error conditions managed by
|
||||||
tt(std::error_category) that is associated with
|
the class tt(ErrorCondition). Also designed as a singleton,
|
||||||
the various error condition enum values, much like tt(CalculatorCategory) was
|
tt(ConditionCategory) contains a vector whose elements hold names and
|
||||||
associated with the tt(CalculatorError) enumeration. The tt(std::error_category)
|
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)
|
verbinsert(-s4 //class examples/errcode/errorcondition/errorcondition.h)
|
||||||
. To create an tt(error_condition) an tt(ErrorCondition::Enum) value
|
|
||||||
is required and the enum's value matching error category.
|
|
||||||
|
|
||||||
|
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,
|
verbinsert(-s4 //demo examples/errcode/errcode/main.cc)
|
||||||
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)
|
|
||||||
|
|
||||||
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>
|
#include <system_error>
|
||||||
|
|
||||||
//enum
|
//calcerrc
|
||||||
enum class CalculatorError
|
enum class CalculatorError
|
||||||
{
|
{
|
||||||
// no 0, since that's by convention implies no error
|
// no 0, since that's by convention implies no error
|
||||||
|
@ -16,19 +16,25 @@ enum class CalculatorError
|
||||||
MissingParentheses, // ( and ) don't match
|
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
|
namespace std
|
||||||
{
|
{
|
||||||
template <>
|
template <>
|
||||||
struct is_error_code_enum<CalculatorError>: public true_type
|
struct is_error_code_enum<CalculatorError>: public true_type
|
||||||
{};
|
{};
|
||||||
}
|
}
|
||||||
|
|
||||||
//=
|
//=
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
#define CLS
|
#define CLS
|
||||||
#define MAIN "main.cc"
|
#define MAIN "main.cc"
|
||||||
#define LIBRARY "modules"
|
|
||||||
#define SOURCES "*.cc"
|
#define SOURCES "*.cc"
|
||||||
#define OBJ_EXT ".o"
|
#define OBJ_EXT ".o"
|
||||||
#define SHAREDREQ ""
|
#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>
|
#include <system_error>
|
||||||
|
|
||||||
//enum
|
//=simerrc
|
||||||
enum class SimulatorError
|
enum class SimulatorError
|
||||||
{
|
{
|
||||||
// no 0
|
// 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
|
namespace std
|
||||||
{
|
{
|
||||||
template <>
|
template <>
|
||||||
|
@ -23,6 +29,10 @@ namespace std
|
||||||
{};
|
{};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::error_code make_error_code(SimulatorError ce);
|
||||||
|
|
||||||
|
extern SimulatorCategory const simulatorCategory;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,8 @@
|
||||||
calculatorerror
|
// specific error categories, defined for this program
|
||||||
simulatorerror
|
calculatorcategory
|
||||||
errorsource
|
simulatorcategory
|
||||||
|
|
||||||
|
// classes handling all error conditions
|
||||||
|
conditioncategory
|
||||||
|
errorcondition
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
#include <system_error>
|
#include <system_error>
|
||||||
|
|
||||||
//calcerrc
|
//enum
|
||||||
enum class CalculatorError
|
enum class CalculatorError
|
||||||
{
|
{
|
||||||
// no 0, since that's by convention implies no error
|
// no 0, since that's by convention implies no error
|
||||||
|
@ -16,25 +16,19 @@ enum class CalculatorError
|
||||||
MissingParentheses, // ( and ) don't match
|
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
|
namespace std
|
||||||
{
|
{
|
||||||
template <>
|
template <>
|
||||||
struct is_error_code_enum<CalculatorError>: public true_type
|
struct is_error_code_enum<CalculatorError>: public true_type
|
||||||
{};
|
{};
|
||||||
}
|
}
|
||||||
|
|
||||||
//=
|
//=
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <tuple>
|
#include <tuple>
|
||||||
|
|
||||||
|
//class
|
||||||
class ConditionCategory: public std::error_category
|
class ConditionCategory: public std::error_category
|
||||||
{
|
{
|
||||||
static ConditionCategory *s_instance;
|
static ConditionCategory *s_instance;
|
||||||
|
@ -25,16 +26,18 @@ class ConditionCategory: public std::error_category
|
||||||
bool equivalent(std::error_code const &code,
|
bool equivalent(std::error_code const &code,
|
||||||
int condition) const noexcept override;
|
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);
|
void addCondition(char const *name, char const *description);
|
||||||
size_t size() const;
|
size_t size() const;
|
||||||
std::string const &operator[](size_t idx) const;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ConditionCategory();
|
ConditionCategory();
|
||||||
};
|
};
|
||||||
|
//=
|
||||||
|
|
||||||
inline void ConditionCategory::addCondition(char const *name,
|
inline void ConditionCategory::addCondition(char const *name,
|
||||||
char const *description)
|
char const *description)
|
||||||
{
|
{
|
||||||
d_conditionInfo.push_back({ name, description });
|
d_conditionInfo.push_back({ name, description });
|
||||||
}
|
}
|
||||||
|
@ -50,6 +53,3 @@ inline std::string const &ConditionCategory::operator[](size_t idx) const
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -5,9 +5,10 @@
|
||||||
// error code and the condition number to verify that the error condition
|
// error code and the condition number to verify that the error condition
|
||||||
// associated with the error_code matches the condition number.
|
// associated with the error_code matches the condition number.
|
||||||
|
|
||||||
|
//impl
|
||||||
bool ConditionCategory::equivalent(std::error_code const &ec, int condNr )
|
bool ConditionCategory::equivalent(std::error_code const &ec, int condNr )
|
||||||
const noexcept
|
const noexcept
|
||||||
{
|
{
|
||||||
return ec.category().equivalent(ec, condNr);
|
return ec.category().equivalent(ec, condNr);
|
||||||
}
|
}
|
||||||
|
//=
|
|
@ -5,6 +5,7 @@
|
||||||
|
|
||||||
#include "../conditioncategory/conditioncategory.h"
|
#include "../conditioncategory/conditioncategory.h"
|
||||||
|
|
||||||
|
//class
|
||||||
class ErrorCondition
|
class ErrorCondition
|
||||||
{
|
{
|
||||||
static ErrorCondition *s_instance;
|
static ErrorCondition *s_instance;
|
||||||
|
@ -31,8 +32,10 @@ class ErrorCondition
|
||||||
private:
|
private:
|
||||||
ErrorCondition(); // singleton, see instance.cc
|
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
|
inline std::string const &ErrorCondition::operator[](size_t nr) const
|
||||||
{
|
{
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
std::error_condition make_error_condition(ErrorCondition::Enum ec)
|
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 CLS
|
||||||
#define MAIN "main.cc"
|
#define MAIN "main.cc"
|
||||||
|
#define LIBRARY "modules"
|
||||||
#define SOURCES "*.cc"
|
#define SOURCES "*.cc"
|
||||||
#define OBJ_EXT ".o"
|
#define OBJ_EXT ".o"
|
||||||
#define SHAREDREQ ""
|
#define SHAREDREQ ""
|
||||||
|
@ -9,7 +10,7 @@
|
||||||
#define CXXFLAGS " --std=c++17 -Wall -O2" \
|
#define CXXFLAGS " --std=c++17 -Wall -O2" \
|
||||||
" -fdiagnostics-color=never "
|
" -fdiagnostics-color=never "
|
||||||
#define IH ".ih"
|
#define IH ".ih"
|
||||||
//#define PRECOMP "-x c++-header"
|
#define PRECOMP "-x c++-header"
|
||||||
#define REFRESH
|
#define REFRESH
|
||||||
#define LDFLAGS ""
|
#define LDFLAGS ""
|
||||||
#define ADD_LIBRARIES ""
|
#define ADD_LIBRARIES ""
|
||||||
|
|
|
@ -1,19 +1,55 @@
|
||||||
#include "main.ih"
|
#include "main.ih"
|
||||||
|
|
||||||
|
//demo
|
||||||
int main()
|
int main()
|
||||||
try
|
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::error_code ec = CalculatorError::TypeError;
|
||||||
assert(ec == ErrorSource::CalcError);
|
|
||||||
assert(ec != ErrorSource::SimError);
|
std::cerr << "Enum value of UnavailCond = " <<
|
||||||
assert(ec != ErrorSource::InputError);
|
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;
|
ec = CalculatorError::ArityError;
|
||||||
std::cout << ec << ' ' << ec.message() << '\n';
|
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 <cassert>
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
// #include <string>
|
#include <string>
|
||||||
// // #include <unordered_map>
|
|
||||||
// #include <system_error>
|
#include <system_error>
|
||||||
|
|
||||||
#include "calculatorerror/calculatorerror.h"
|
#include "calculatorerror/calculatorerror.h"
|
||||||
|
#include "calculatorcategory/calculatorcategory.h"
|
||||||
|
|
||||||
#include "simulatorerror/simulatorerror.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::error_code ec = CalculatorError::ArityError;
|
||||||
std::cout << ec << ' ' << ec.message() << '\n';
|
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 &se)
|
||||||
{
|
{
|
||||||
std::cout << se.what() << ": " << se.code() << '\n';
|
std::cout << se.what() << ":\n"
|
||||||
|
" " << se.code() << '\n';
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Outputs:
|
Outputs:
|
||||||
calculator:4 incorrect number of arguments
|
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>
|
#include <system_error>
|
||||||
|
|
||||||
//=simerrc
|
//enum
|
||||||
enum class SimulatorError
|
enum class SimulatorError
|
||||||
{
|
{
|
||||||
// no 0
|
// 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
|
namespace std
|
||||||
{
|
{
|
||||||
template <>
|
template <>
|
||||||
|
@ -29,10 +23,6 @@ namespace std
|
||||||
{};
|
{};
|
||||||
}
|
}
|
||||||
|
|
||||||
std::error_code make_error_code(SimulatorError ce);
|
|
||||||
|
|
||||||
extern SimulatorCategory const simulatorCategory;
|
|
||||||
|
|
||||||
#endif
|
#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