Qx v0.5.7
Qt Extensions Library
Loading...
Searching...
No Matches
qx-abstracterror.h
Go to the documentation of this file.
1#ifndef QX_ABSTRACTERROR_H
2#define QX_ABSTRACTERROR_H
3
4// Shared Lib Support
5#include "qx/core/qx_core_export.h"
6
7// Standard Library Includes
8#include <array>
9#include <concepts>
10
11// Qt Includes
12#include <QString>
13#include <QHash>
14#include <QSet>
15
16// Intra-component Includes
17#include "qx/core/qx-global.h"
18
19// Extra-component Includes
20#include "qx/utility/qx-stringliteral.h"
21
22using namespace Qt::Literals::StringLiterals;
23
24namespace Qx
25{
26
27class QX_CORE_EXPORT IError
28{
29 friend class Error;
30//-Class Variables----------------------------------------------------------------------------------------------------------
31private:
32 static inline const QString T_CODE_DUPE = u"Error type code %1 is already claimed by %2!"_s;
33 static inline const QString T_NAME_DUPE = u"Error type name %1 is already claimed!"_s;
34 static inline const QString T_CODE_RESERVED = u"Error type code %1 is reserved!"_s;
35 static inline constinit QHash<quint16, const QString*> codeRegistry;
36 static constexpr std::array<QStringView, 8> RESERVED_NAMES{
37 u"Qx::InternalError",
38 u"Qx::GenericError",
39 u"Qx::IoOpReport",
40 u"Qx::SystemError",
41 u"Qx::DownloadManagerReport",
42 u"Qx::DownloadOpReport",
43 u"Qx::JsonError",
44 u"QJsonParseError"
45 };
46 // TODO: If this becomes sufficiently large, move to a constexpr set (hopefully available in std by that time)
47
48//-Class Functions----------------------------------------------------------------------------------------------------------
49private:
50 static QSet<QString>& nameRegistry(); // RAII
51
52protected:
53 // Implementation detail
54 static bool registerType(quint16 tc, const QString& tn);
57//-Constructor----------------------------------------------------------------------------------------------------------
58protected:
59 IError() = default;
60
61//-Instance Functions------------------------------------------------------------------------------------------------------
62protected:
63 virtual quint32 deriveValue() const;
64 virtual Severity deriveSeverity() const;
65 virtual QString deriveCaption() const;
66 virtual QString derivePrimary() const;
67 virtual QString deriveSecondary() const;
68 virtual QString deriveDetails() const;
69
70 /* TODO: Consider changing deriveSeverity to be a fixed function that always returns a protected member variable
71 * that descendants modify instead. Its less clean, but would allow for base class withSeverity() and setSeverity()
72 * methods such that the severity of any error can always be manipulated (which is somewhat common to all potential
73 * error type). Of course this would also require use of CRTP to allow for the functions to return the correct type.
74 * This could also be done for isValid() where an underlying value is always checked, though some error types
75 * might not quite operate that way (e.g. IoOpReport).
76 */
77
78//-Operators-------------------------------------------------------------------------------------------------------
79public:
80 bool operator==(const IError& other) const = default;
81 bool operator!=(const IError& other) const = default;
82};
83
84template<StringLiteral EName, quint16 ECode>
85class AbstractError : protected IError
86{
87friend class Error;
88//-Class Variables----------------------------------------------------------------------------------------------------------
89public:
90 static constexpr quint16 TYPE_CODE = ECode;
91 static constexpr QLatin1StringView TYPE_NAME{EName.value};
92
93private:
94 static const bool REGISTER;
95
96//-Constructor-------------------------------------------------------------------------------------------------------------
97protected:
98 AbstractError() = default;
99
100//-Class Functions----------------------------------------------------------------------------------------------------------
101private:
102 using IError::registerType;
103
104//-Operators-------------------------------------------------------------------------------------------------------
105public:
106 bool operator==(const AbstractError& other) const = default;
107 bool operator!=(const AbstractError& other) const = default;
108 operator bool() const { return deriveValue() > 0; };
109};
110
111/* TODO: Get string of the type automatically when it becomes
112 * more feasible. std::source_location is a good candidate once support
113 * for it is more widespread, though since it mainly focuses of function
114 * names and not classes, it alone might not be enough
115 */
116
117//-Namespace Concepts-------------------------------------------------------------------------------------------------------
118
119/* TODO: Clang 12 doesn't support the C++20 feature "Lambdas in unevaluated contexts",
120 * so this helper function needs to be used instead. Once moving on to at least Clang 13
121 * as the minimum supported version instead the lambda commented out below can be used
122 * instead.
123 */
124//template<class E>
125//concept error_type = requires(E type) {
126// // IIFE that ensures E is a specialization of AbstractError
127// []<StringLiteral Y, quint16 Z>(AbstractError<Y, Z>&){}(type);
128//};
129
130/* Define error type registrar variable. This must be done out of line to ensure that only
131 * one instance of the variable exists per-error-type across an entire program. If the variable
132 * is defined inline, multiple versiosn of it can exist in parallel when linking via shared-libraries,
133 * if those libraries are used by multiple targets in the same project. This would cause an error type
134 * to call registerType() multiple times.
135 */
136template<StringLiteral EName, quint16 ECode>
137const bool AbstractError<EName, ECode>::REGISTER = registerType(TYPE_CODE, TYPE_NAME);
138
140namespace AbstractErrorPrivate
141{
142 template<Qx::StringLiteral Y, quint16 Z>
143 void aeDerived(Qx::AbstractError<Y, Z>&);
144}
147template<class E>
148concept error_type = requires(E type) {
149 AbstractErrorPrivate::aeDerived(type);
150};
151
152template<class A>
155 !std::move_constructible<A> &&
156 !std::copy_constructible<A>;
157
158template<class Able, class Ater>
159concept error_adaptation = error_adapter<Ater> && std::constructible_from<Ater, const Able&>;
160
161}
162
163//-Macros----------------------------------------------------------------------------------------------------------
164#define QX_ERROR_TYPE(Type, Name, Code) \
165 Type final : public Qx::AbstractError<Name, Code>
166
167#endif // QX_ABSTRACTERROR_H
The AbstractError template class completes the Error interface and acts as the base class from which ...
Definition qx-abstracterror.h:86
static constexpr QLatin1StringView TYPE_NAME
Definition qx-abstracterror.h:91
bool operator==(const AbstractError &other) const =default
static constexpr quint16 TYPE_CODE
Definition qx-abstracterror.h:90
bool operator!=(const AbstractError &other) const =default
The Error class acts as an interface for an extensible variety of error objects.
Definition qx-error.h:38
IError defines the baseline inheritance interface for Qx error types.
Definition qx-abstracterror.h:28
bool operator!=(const IError &other) const =default
virtual quint32 deriveValue() const
Definition qx-abstracterror.cpp:78
IError()=default
bool operator==(const IError &other) const =default
Specifies that two types form a Qx error adaptation.
Definition qx-abstracterror.h:159
Specifies that a type is a Qx error adapter.
Definition qx-abstracterror.h:153
Specifies that a type is a Qx error type.
Definition qx-abstracterror.h:148
The Qx namespace is the main namespace through which all non-global functionality of the Qx library i...
Definition qx-processwaiter.cpp:5
Severity
Definition qx-global.h:11