Qx v0.5.7
Qt Extensions Library
Loading...
Searching...
No Matches
Qx::Error Class Reference

The Error class acts as an interface for an extensible variety of error objects. More...

#include <qx/core/qx-error.h>

Collaboration diagram for Qx::Error:
[legend]

Public Member Functions

 Error ()
 
template<class EAble , class EAter = typename AdapterRegistry<EAble>::adapter>
requires error_adaptation<EAble, EAter>
 Error (const EAble &adapted)
 
template<class ErrorType >
requires error_type<ErrorType>
 Error (const ErrorType &e)
 
QString caption () const
 
quint64 code () const
 
QString details () const
 
bool equivalent (const Error &other) const
 
QString hexCode () const
 
bool isValid () const
 
 operator bool () const
 
bool operator!= (const Error &other) const =default
 
bool operator== (const Error &other) const =default
 
QString primary () const
 
QString secondary () const
 
ErrorsetSeverity (Severity sv)
 
Severity severity () const
 
QString severityString (bool uc=true) const
 
QString toString () const
 
quint16 typeCode () const
 
QLatin1StringView typeName () const
 
quint32 value () const
 
Error withSeverity (Severity sv)
 

Static Public Attributes

static constexpr quint16 TYPE_CODE = 0
 
static constexpr QLatin1StringView TYPE_NAME {"Error"}
 

Friends

QTextStreamoperator<< (QTextStream &ts, const Error &e)
 

Detailed Description

Error provides a common interface suitable for communicating most forms of error information in a unified manner. Additionally, it acts as a generic container for said information by being constructable from all derived types, providing a pseudo-polymorphic conversion mechanism with value semantics that obviates the need for typecasting and dealing with pointer semantics. Because error objects are only created when unexpected behavior occurs, and often immediately after a performance sensitive routine is paused or halted, the overhead of creating an Error object this way is generally negligible.

Additional error types are created by extending the AbstractError template class.

Technically, the underlying inheritance interface is defined by IError/AbstractError, but Error functionally acts similar to a traditional base class pointer in that it is used to access the data of extended error types in a generalized manner.

In order to provide consistent and useful context, the design of the interface is centered around two primary tenets:

All error types (represented by actual types) have a

  • Type name
  • Type code

while all errors have (at minimum) a

The type name and type code of an error type can be retrieved via the type's public members TYPE_NAME and TYPE_CODE respectively, or by the typeCode() and typeName() methods of an Error object created from that type. The uniqueness of each type name and code is guaranteed via runtime assertions (assuming they are not disabled, i.e. in a Release configuration). Uniqueness of error values within a given type is not enforced but a sensible implementation will ensure they do not overlap.

Example

The following minimal example demonstrates some of the ways that Qx::Error can be used in a polymorphic-like fashion.

#include <QList>
#include <qx/core/qx-iostream.h>
// Realistically these custom error types would be fleshed out much more
class BadError final : public Qx::AbstractError<"BadError", 1000>
{
public:
enum Type
{
NoError = 0,
Bad = 1,
Worse = 2
};
private:
Type mValue;
public:
BadError() :
mValue(NoError)
{}
BadError(Type type) :
mValue(type)
{}
private:
quint32 deriveValue() const override { return mValue; }
QString derivePrimary() const override { return "Bad error occurred."; }
QString deriveSecondary() const override { return QString("Error type %1").arg(mValue); }
public:
bool isProblem() { return mValue != NoError; }
};
class BigBadError final : public Qx::AbstractError<"BigBadError", 1001>
{
public:
enum Type
{
NoError = 0,
Big = 1,
Bigger = 2
};
private:
Type mValue;
public:
BigBadError() :
mValue(NoError)
{}
BigBadError(Type type) :
mValue(type)
{}
private:
quint32 deriveValue() const override { return mValue; }
QString derivePrimary() const override { return "Big bad error occurred."; }
QString deriveSecondary() const override { return QString("Error type %1").arg(mValue); }
public:
bool isProblem() { return mValue != NoError; }
};
BadError procedure()
{
//...
bool problem = true; // For demonstration purposes
if(problem)
return BadError(BadError::Bad);
//...
return BadError();
}
BigBadError bigProcedure()
{
//...
bool hugeProblem = true; // For demonstration purposes
if(hugeProblem)
return BigBadError(BigBadError::Bigger);
//...
return BigBadError();
}
Qx::Error doStuff()
{
//...
BadError be = procedure();
if(be.isProblem())
return be;
BigBadError bbe = bigProcedure();
if(bbe.isProblem())
return bbe;
//...
return Qx::Error();
}
int main()
{
//...
errors << BadError(BadError::NoError);
errors << doStuff();
//...
for(const Qx::Error& e : errors)
{
// Print first valid error
if(e.isValid())
{
Qx::cout << "First Error:\n" << e;
break;
}
}
//...
return 0;
}

A complete error code(), which combines the type code and error value into one identifiable number, along with other error information can be accessed via the methods of this class.

Unlike most interface base classes an Error object can be instantiated directly via its default constructor in order to produce an invalid error.

Error Adapters and Adaptations

To further streamline error handling, any existing arbitrary (presumably error related) type not derived from AbstractError can be adapted to the Error interface via an Error Adapter.

An error adapter is a specific derivation of AbstractError, in which the class is not move/copy constructable and is constructable from the type it's designed to adapt (see Qx::error_adapter). Each pair of adapter and adapted type is considered an Error Adaptation (see Qx::error_adaptation). and an instance of Error can be constructed from any valid Error Adaptation. Adaptations must be explicitly registered via the QX_DECLARE_ERROR_ADAPTATION() macro.

Error Adapters are only intended to be instantiated briefly by the appropriate Error constructor, hence the move/copy construction restriction, so it is recommended to compose an adapter such that it directly accesses the adapted type via a constant reference.

The following example shows how one might create an Error Adaptation for QSqlError.

#include <qx/core/qx-iostream.h>
#include <QSqlError>
class QSqlErrorAdapter final : public Qx::AbstractError<"QSqlError", 1200>
{
private:
const QSqlError& mErrorRef;
public:
QSqlErrorAdapter(const QSqlError& e) :
mErrorRef(e)
{}
QSqlErrorAdapter(QSqlErrorAdapter&&) = delete;
QSqlErrorAdapter(const QSqlErrorAdapter&) = delete;
private:
quint32 deriveValue() const override { return mErrorRef.type(); }
QString derivePrimary() const override { return "An SQL error occurred."; }
QString deriveSecondary() const override { return mErrorRef.text(); }
};
int main(int argc, char *argv[])
{
// Example QSqlError
QSqlError e("Faulty Driver", "Issue loading driver", QSqlError::ConnectionError);
// Print via Qx::Error overload of QTextStream::operator<<()
Qx::cout << e;
}
// Prints:
/*
* ( ERROR ) 0x0204B000000001
* An SQL error occurred.
* Issue loading driver Faulty Driver
*/
See also
AbstractError, GenericError.

Constructor & Destructor Documentation

◆ Error() [1/3]

Qx::Error::Error ( )

Constructs an invalid error.

See also
isValid().

◆ Error() [2/3]

template<class ErrorType >
requires error_type<ErrorType>
Qx::Error::Error< ErrorType > ( const ErrorType & e)
inline

Constructs a standard error object from the specific error e of type ErrorType.

◆ Error() [3/3]

template<class EAble , class EAter = typename AdapterRegistry<EAble>::adapter>
requires error_adaptation<EAble, EAter>
Qx::Error::Error< EAble, EAter > ( const EAble & adapted)
inline

Constructs a standard error object from adapted using its corresponding error adapter EAter.

Member Function Documentation

◆ caption()

QString Qx::Error::caption ( ) const

Returns the error's caption.

The caption is the heading of an error.

The default implementation of Error produces an empty string.

◆ code()

quint64 Qx::Error::code ( ) const

Returns the errors code.

An error's code is a combination of its type code, value, and severity; however, an invalid error's code is always 0 regardless of its type code.

Error Code Format
Post interpretation 64-bit unsigned integer independent of host byte order
63 - 56 55 - 48 47 - 32 31 - 0
Reserved Severity Type Value

For example, an error with a type code of 1010, error value of 4500 and severity of Err will have the code 4337916973460.

The original type code and error value can be obtained by separating the low-order and high-order parts of this value.

See also
value(), typeCode() and hexCode().

◆ details()

QString Qx::Error::details ( ) const

Returns a string that contains additional details regarding the error.

The error details usually contain any remaining error information not otherwise shown in the primary and secondary information, or complete error details that generally are not of interest to an application's end user, but are useful for error reports and debugging.

See also
primary() and secondary().

◆ equivalent()

bool Qx::Error::equivalent ( const Error & other) const

Returns true if this error's type code and value and other's type code and value are the same; otherwise, returns false.

This is useful to check if two error's describe the same specific type of fault, even if some other minor details are different.

See also
operator==().

◆ hexCode()

QString Qx::Error::hexCode ( ) const

Returns a string containing a hexadecimal representation of the error's code.

For example, an error with a type code of 1010, error value of 4500 and severity of Err will produce the hex code string 0x0203F200001194.

See also
value(), typeCode(), and code().

◆ isValid()

bool Qx::Error::isValid ( ) const

Returns true if the error's value is greater than 0; otherwise, returns false.

Invalid errors are generally used to indicate the success of an operation.

If an error is invalid, it's severity is generally meaningless.

See also
value().

◆ operator bool()

Qx::Error::operator bool ( ) const

A convenience operator to check if the error is valid. Produces true if the value of the error is greater than 0; otherwise, produces false.

See also
isValid().

◆ operator!=()

bool Qx::Error::operator!= ( const Error & other) const
default

Returns true if this error is not the same as other; otherwise, returns false.

◆ operator==()

bool Qx::Error::operator== ( const Error & other) const
default

Returns true if this error is the same as other; otherwise, returns false.

See also
equivalent().

◆ primary()

QString Qx::Error::primary ( ) const

Returns a string that contains primary error information.

Generally this is the action that ultimately lead to the failure, or the overarching form of the error, while secondary() usually contains more specific info.

For example, an Error recording a file write failure may contain the following error info:

Primary - "Failed to write file 'write_me.txt'." Secondary - "Permission denied."

See also
secondary().

◆ secondary()

QString Qx::Error::secondary ( ) const

Returns a string that contains secondary error information.

The secondary error string usually explains why an error occurred, or otherwise notes more specific error information.

See also
primary() and details().

◆ setSeverity()

Error & Qx::Error::setSeverity ( Severity sv)

Changes the severity of the error to sv and returns a reference to the error.

Although Error instances are otherwise immutable, this function allows changing the error's severity level since the severity of an error may vary depending on the context in which it occurs.

See also
severity() and withSeverity();

◆ severity()

Severity Qx::Error::severity ( ) const

Returns the severity of the error.

The severity denotes the urgency with which the the rest of the contained error information should be regarded.

This is most often use to decorate error message windows or control program flow, like halting execution altogether in the event of a Critical error.

The most common setting is Error.

◆ severityString()

QString Qx::Error::severityString ( bool uc = true) const

Returns the string representation of the error's severity.

If uc is set to true, the returned string is entirely in uppercase.

◆ toString()

QString Qx::Error::toString ( ) const

Returns a single string that contains the error's severity, code, primary info, and secondary info.

See also
severityString().

◆ typeCode()

quint16 Qx::Error::typeCode ( ) const

Returns the type code of the type from which this error was constructed.

See also
AbstractError::TYPE_CODE

◆ typeName()

QLatin1StringView Qx::Error::typeName ( ) const

Returns the type name of the type from which this error was constructed.

See also
AbstractError::TYPE_NAME

◆ value()

quint32 Qx::Error::value ( ) const

Returns the value (i.e. type specific code) of the error.

This value can be used to programmatically identify the exact form of error that occurred.

See also
code() and typeCode().

◆ withSeverity()

Error Qx::Error::withSeverity ( Severity sv)

Returns a copy of the error with the severity set to sv.

See also
severity() and setSeverity();

Friends And Related Symbol Documentation

◆ operator<<

QTextStream & operator<< ( QTextStream & ts,
const Error & e )
friend

Writes the error e to the stream ts.

The error is written in a human-readable format, structured by its properties. A new line is always started after the error is written.

See also
postError().
ge.setValue(50);
ge.setCaption("Caption");
ge.setPrimary("Generic Error");
ge.setSecondary("There was an Error");
ge.setDetailed("- Issue 1\n- Issue2\n- Issue3");
ts << Qx::Error(ge);
// Prints:
/*
* (WARNING) 0x00000032 Caption
* Generic Error
* There was an Error
*
* Details:
* --------
* - Issue 1
* - Issue 2
* - Issue 3
*/
The Error class acts as an interface for an extensible variety of error objects.
Definition qx-error.h:38
The GenericError class is multi-purpose container for storing error information.
Definition qx-genericerror.h:14
GenericError & setCaption(const QString &caption)
Definition qx-genericerror.cpp:139
GenericError & setSeverity(Severity sv)
Definition qx-genericerror.cpp:119
GenericError & setSecondary(const QString &secondary)
Definition qx-genericerror.cpp:153
GenericError & setPrimary(const QString &primary)
Definition qx-genericerror.cpp:146
virtual QString deriveSecondary() const
Definition qx-abstracterror.cpp:124
QTextStream cout
Definition qx-iostream.h:13
@ Warning
Definition qx-global.h:12
QString text() const const
QSqlError::ErrorType type() const const
QString arg(Args &&... args) const const
The qx-error.h header file provides access to the Error interface.
#define QX_DECLARE_ERROR_ADAPTATION(Adaptable, Adapter)
Definition qx-error.h:132

Member Data Documentation

◆ TYPE_CODE

quint16 Qx::Error::TYPE_CODE = 0
staticconstexpr

Technically the type code of Error itself is never used since only invalid errors can be created directly with its constructor; however, this variable contains the value 0 for consistency with the rest of the type interface.

◆ TYPE_NAME

QString Qx::Error::TYPE_NAME {"Error"}
staticconstexpr

A string representation of the type name, in this case Error.


The documentation for this class was generated from the following files: