diff --git a/annotations/yo/advancedtemplates/errorcategory.yo b/annotations/yo/advancedtemplates/errorcategory.yo new file mode 100644 index 00000000..34271ba3 --- /dev/null +++ b/annotations/yo/advancedtemplates/errorcategory.yo @@ -0,0 +1,68 @@ +The tt(ErrorCodeEnums) developed in the previous section are the starting +points for two more classes, derived from the class tt(error_category) (see +section ref(ERRCAT). + +Our own error category classes are designed as singleton classes, dervied from +tt(std::error_category), and merely have to implement their own tt(name, +message) and an tt(equivalent) function. + +Associated with errors defined by tt(ErrorCodeEnums) are two textual items +(NTBSs): a verbal description of the error, and the name of the em(error +condition) to which the enum value belongs. E.g., associated with +tt(CalculatorError:::MissingParentheses) are the description tt("parentheses +don't match") and the error condition name tt("InputCond"). Those associations +are collected in a class template tt(CatMap), which has been 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) + + As tt(ErrorCodeEnum)-values may have been randomly assigned (not using 0) +a tt(CapMap) offers fast access to the error's description and error condition +name. + +To definine an error category class we take the following steps: +itemization( +it() First the class's interface is designed. The interface of the class + tt(CalculatorCategory) is shown here, the interface of + tt(SimulatorCategory) is analogously designed. Their setup is fairly + basic; being a singleton class its (default) constructor is private, and + a static member tt(instance) returns a reference to the class's sole + object. A second static member (tt(CatMap s_errors) is initialized with + tt(ErrorCodeEnum) values and their descriptions and error condition + names: + + verbinsert(//class + examples/errcode2/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) + + The member tt(name) simply returns a short string naming the category + (tt("calculator") for the calculator category). + +it() Next, the The class's tt(message) member is defined. It returns the + description matching values of the category's error code enum values. + error code and returns its description. Here is the definition of the + tt(message) member, and the initialization of the tt(CatMap s_errors) + static data member: + verbinsert(//impl examples/errcode2/calculatorcategory/messace.cc) + verbinsert(//impl examples/errcode2/calculatorcategory/data.cc) + +it() + +it() Fifth, 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) + + Now that tt(CalculatorErrc) is an tt(std::error_code) we can use it in our + programs. Here is a little program illustrating its use: + + verbinsert(-a examples/errcode2/main.part); + + In the next section using error conditions is covered in detail. + ) + diff --git a/annotations/yo/advancedtemplates/errorcode.yo b/annotations/yo/advancedtemplates/errorcode.yo index a45d276d..195c09ad 100644 --- a/annotations/yo/advancedtemplates/errorcode.yo +++ b/annotations/yo/advancedtemplates/errorcode.yo @@ -27,8 +27,8 @@ ref(ERRCAT). Error conditions are used to associate error values with generic causes of errors. Since error conditions may previously have been defined (maybe by different developers) it is an interesting puzzle by itself to figure out how multiple error conditions can flexibly be combined in one -program. This puzzle is solved by defining a class tt(ErrorSource) that -manages error conditions. +program. This puzzle is solved by defining a class tt(ErrorCondition) that is +able to manage all error conditions. The example used below focuses on the construction of a flight simulator. When using the flight simulator itself several errors may be encountered (e.g., a @@ -45,7 +45,6 @@ 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) The class tt(std::error_code) is designed so that two pieces of @@ -55,18 +54,18 @@ it() Our first step consists of defining our own error enumerations: one it() Second, our intention is to let tt(error_code) accept tt(CalculatorError) and tt(SimulatorError) values using its - tt(error_code(ErrorCodeEnum)) constructor, as this allows us to + tt(error_code(ErrorCodeEnum)) constructor as this allows us to retrieve error values and categories, using our own error code enumerations. - To achieve this, the trait class ti(is_error_code_enum), must be - available for our error enumeration. This trait class's static member - tt(value) must return tt(true). Interestingly, defining the - specializations of tt(std::is_error_code_enum) requires us to add code - to the tt(std) namespace. Normally this is not allowed, but in this - case it is. The bf(C++) standard states: + To achieve that the trait class ti(is_error_code_enum's) static member + tt(value) must return tt(true) when provided with a + value from our own error enumeration. This trait class. Interestingly, + defining the specializations of tt(std::is_error_code_enum) requires us to + add code to the tt(std) namespace. Normally this is not allowed, but in + this case it is. The bf(C++) standard states: - quote( 20.5.4.2.1 Namespace std + quote(20.5.4.2.1 Namespace std The behavior of a C++ program is undefined if it adds declarations or definitions to namespace std or to a namespace within namespace std @@ -81,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/calculatorerror.h) + verbinsert(//trait examples/errcode2/calculatorerror/.h) This completes the definition of our own error enumerations, which are now `promoted' to tt(ErrorCodeEnums). @@ -93,51 +92,7 @@ it() Third, one of the constructors of tt(error_code) objects expects, in object. That constructor normally casts the tt(ErrorCodeEnum) value to an tt(int), and constructs the tt(error_code) by also specifying a fitting tt(error_category). Therefore, a class matching the tt(ErrorCodeEnum) is - derived from tt(error_category). - - Our own error category classes are designed as singleton classes and - merely have to implement their own tt(name, message) and one - tt(equivalent) function. tt(Message) members return descriptions matching - values of error code enums, and for that we use a tt(std::unordered_map), - for which the tt(typedef CatMap) is defined (since - tt(ErrorCodeEnum)-values may have been randomly assigned (not using 0) an - tt(unordered_map) offers fast access to the error's description and error - condition (see the next section) given its value). Here is the interface - of the class tt(CalculatorCategory): - - verbinsert(//class - examples/errcode2/calculatorcategory/calculatorcategory.h) - - As error category objects are singletons error categories can simply be - compared for (in)equality by comparing the addresses of their singleton - objects. - -it() Fourth, the class's tt(name) member simply returns a short string naming - the category (tt("calculator") for the calculator category). - - The class's tt(message) member locates the tt(CatMap) entry matching the - error code and returns its description. Here are the definitions of the - tt(message) member, of the member tt(instance) returning a reference to - the class's single object, and to the initialization of its tt(CatMap) - static data member: - - verbinsert(//impl examples/errcode2/calculatorcategory/messace.cc) - - verbinsert(//impl examples/errcode2/calculatorcategory/instance.cc) - - verbinsert(//impl examples/errcode2/calculatorcategory/data.cc) - -it() Fifth, 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) - - Now that tt(CalculatorErrc) is an tt(std::error_code) we can use it in our - programs. Here is a little program illustrating its use: - - verbinsert(-a examples/errcode2/main.part); - - In the next section using error conditions is covered in detail. - ) + usually derived from tt(error_category). Deriving a class from + tt(error_category) is covered in the next section. +) diff --git a/annotations/yo/advancedtemplates/examples/errcode2/calculatorcategory/calculatorcategory.h b/annotations/yo/advancedtemplates/examples/errcode2/calculatorcategory/calculatorcategory.h index f8744d38..9ef870d4 100644 --- a/annotations/yo/advancedtemplates/examples/errcode2/calculatorcategory/calculatorcategory.h +++ b/annotations/yo/advancedtemplates/examples/errcode2/calculatorcategory/calculatorcategory.h @@ -16,11 +16,10 @@ class CalculatorCategory: public std::error_category public: static CalculatorCategory &instance(); - bool equivalent(std::error_code const &ec, int condNr) const noexcept - override; char const *name() const noexcept override; std::string message(int ce) const override; - + bool equivalent(std::error_code const &ec, int condNr) const noexcept + override; private: CalculatorCategory() = default; }; diff --git a/annotations/yo/advancedtemplates/examples/errcode2/catmap/catmap.h b/annotations/yo/advancedtemplates/examples/errcode2/catmap/catmap.h index bb483cca..9b42f509 100644 --- a/annotations/yo/advancedtemplates/examples/errcode2/catmap/catmap.h +++ b/annotations/yo/advancedtemplates/examples/errcode2/catmap/catmap.h @@ -4,6 +4,7 @@ #include #include +//impl template class CatMap: public std::unordered_map< Enum, @@ -18,9 +19,11 @@ class CatMap: public std::unordered_map< }; template -CatMap::CatMap(std::initializer_list const &list) +CatMap::CatMap( + std::initializer_list const &list) : Map{ list } {} +//= #endif diff --git a/annotations/yo/advancedtemplates/examples/errcode2/simulatorcategory/simulatorcategory.h b/annotations/yo/advancedtemplates/examples/errcode2/simulatorcategory/simulatorcategory.h index 643ab229..28ccb15a 100644 --- a/annotations/yo/advancedtemplates/examples/errcode2/simulatorcategory/simulatorcategory.h +++ b/annotations/yo/advancedtemplates/examples/errcode2/simulatorcategory/simulatorcategory.h @@ -15,11 +15,10 @@ class SimulatorCategory: public std::error_category public: static SimulatorCategory &instance(); - bool equivalent(std::error_code const &ec, int condNr) const noexcept - override; char const *name() const noexcept override; std::string message(int ce) const override; - + bool equivalent(std::error_code const &ec, int condNr) const noexcept + override; private: SimulatorCategory() = default; };