ALib C++ Library
Library Version: 2511 R0
Documentation generated by doxygen
Loading...
Searching...
No Matches
enum.inl
Go to the documentation of this file.
1//==================================================================================================
2/// \file
3/// This header-file is part of module \alib_boxing of the \aliblong.
4///
5/// \emoji :copyright: 2013-2025 A-Worx GmbH, Germany.
6/// Published under \ref mainpage_license "Boost Software License".
7//==================================================================================================
8ALIB_EXPORT namespace alib { namespace boxing {
9
10//==================================================================================================
11/// This class is useful to pass and accept enum values of arbitrary C++ scoped enum types.
12/// Based on class \alib{boxing;Box}, all interfaces are inherited, including type guessing and
13/// unboxing.
14///
15/// In the constructor, enum elements of an arbitrary type are accepted.
16/// The element's underlying integral value is boxed, and thus run-time type-information is added.
17/// Having the "original" element stored in protected base class \b Box, has the following
18/// advantages:
19///
20/// \note
21/// The implementation of this class, by deriving from class \b Box, introduces a
22/// small memory overhead (usually 8 bytes per instance on 64-bit system), in respect to a
23/// possible alternative "direct" implementation. This is due to the fact that boxing allows
24/// one-dimensional array types to be boxed as well as scalar types - which is never the case
25/// with this class.<br>
26/// But the advantages of doing so certainly surpass this small drawback.
27///
28/// \note
29/// Class \b Box is inherited \c protected instead of public, to hide bigger portions of
30/// the base class's interface. While some functions are explicitly made visible with
31/// keyword \c using, for others, instances of this class have to be cased using
32/// overloaded methods #CastToBox.
33///
34/// ## Functors In Namespace std ##
35/// Functors <c>std::hash</c>, <c>std::equal_to</c> and <c>std::less</c> are specialized for this
36/// type with the inclusion of the header-file \implude{Boxing.StdFunctors}
37/// as documented with namespace #alib::boxing::compatibility::std.
38///
39/// ## Friends ##
40/// class \alib{boxing;Box}
41///
42/// @see With the inclusion of the module \alib_enumrecords in the \alibbuild, the namespace functions
43/// \alib{boxing;GetRecord} and \alib{boxing;TryRecord} become available, which receive an
44/// enum record for a value of this class.
45//==================================================================================================
46struct Enum : protected Box
47{
48 #if !DOXYGEN
49 friend class Box;
50 #endif
51
52 /// Default constructor.
54 : Box(nullptr) {}
55
56 /// Implicit constructor, which accepts arbitrary elements of scoped or non-scoped enum types.
57 ///
58 /// @tparam TEnum The external (user specific) enumeration type.
59 /// @param element The external (user specific) enumeration element.
60 template<typename TEnum>
61 requires std::is_enum<TEnum>::value
62 constexpr Enum( TEnum element )
63 : Box( element ) {}
64
65 /// This is a shortcut to \alib{boxing;Box::Unbox;Box::Unbox<TEnum>()} to retrieve the
66 /// original enum element in a type-safe way.
67 ///
68 /// Before invoking this, the boxed type can be checked with #IsType. If the wrong type
69 /// is tried to be received, an \alib_assertion is raised.
70 ///
71 /// @tparam TEnum The external (user specific) enumeration type.
72 /// @return The underlying integral value of the encapsulated enum element.
73 template<typename TEnum>
74 requires std::is_enum<TEnum>::value
75 TEnum Get() const { return Unbox<TEnum>(); }
76
77 /// Returns the underlying integral value of the original enum element cast to type
78 /// \alib{integer}.
79 ///
80 /// \note
81 /// Boxed enum element values are always
82 /// \ref alib_boxing_enums_integer "stored as type integer", regardless of the
83 /// underlying type of the enumeration.
84 ///
85 /// @return The underlying integral value.
86 integer Integral() const { return data.Integrals.Array[0]; }
87
88 /// Comparison operator.
89 ///
90 /// @param rhs The right-hand side argument of the comparison.
91 /// @return \c true if this object equals \p{rhs}, \c false otherwise.
92 bool operator==(const Enum& rhs) const { return this->CastToBox() == rhs.CastToBox(); }
93
94 /// Comparison operator.
95 ///
96 /// @param rhs The right-hand side argument of the comparison.
97 /// @return \c true if this object does not equal \p{rhs}, \c false otherwise.
98 bool operator!=(const Enum& rhs) const { return this->CastToBox() != rhs.CastToBox(); }
99
100 #if DOXYGEN
101 /// Imports \c protected base class's method \alib{boxing;Box::TypeID}.
102 /// @return The \c std::type_info of the mapped \c enum type.
103 using Box::TypeID;
104
105 /// Imports \c protected base class's method \alib{boxing;Box::Hashcode}.
106 /// @return A hashcode for the boxed enum type and value.
107 using Box::Hashcode;
108 #else
109 using Box::TypeID;
110 using Box::Hashcode;
111 #endif
112
113 /// This method casts an instance of this class to a reference of base class \b Box.
114 /// To hide the bases class's interface, this class inherits class \b Box only as
115 /// a \c protected base. With this method, this "artificial limitation " (its a design decision)
116 /// is lifted.
117 ///
118 /// @return A mutable reference to this object.
119 Box& CastToBox() { return static_cast<Box&>(*this); }
120
121 /// Same as overloaded version, but returns a \c const reference and consequently this method
122 /// is declared\c const itself.
123 ///
124 /// @return A constant reference to this object.
125 const Box& CastToBox() const { return static_cast<const Box&>(*this); }
126
127
128 /// Checks if this instance has an enum element of type \p{TEnum} stored.<br>
129 /// This method is an inlined, simple alias for \c protected base class's method
130 /// \alib{boxing;Box::IsType}.
131 ///
132 ///
133 /// @tparam TEnum The external (user specific) enumeration type.
134 /// @return \c true if the encapsulated enum type of type \p{TEnum}, otherwise \c false.
135 template<typename TEnum>
136 requires std::is_enum<TEnum>::value
137 bool IsEnumType() const { return Box::IsType<TEnum>(); }
138
139 /// Comparison operator with enum elements.
140 ///
141 /// @tparam TEnum The external (user specific) enumeration type.
142 /// @param rhs The right-hand side argument of the comparison.
143 /// @return \c true if this object equals \p{rhs}, \c false otherwise.
144 template<typename TEnum>
145 requires std::is_enum<TEnum>::value
146 bool operator==(TEnum rhs) const {
147 return Integral() == static_cast<typename std::underlying_type<TEnum>::type>( rhs )
148 && TypeID() == typeid( TEnum );
149 }
150
151 /// Comparison operator with enum elements.
152 ///
153 /// @tparam TEnum The external (user specific) enumeration type.
154 /// @param rhs The right-hand side argument of the comparison.
155 /// @return \c true if this object does not equal \p{rhs}, \c false otherwise.
156 template<typename TEnum>
157 requires std::is_enum<TEnum>::value
158 bool operator!=(TEnum rhs) const {
159 return Integral() != static_cast<typename std::underlying_type<TEnum>::type>( rhs )
160 || TypeID() != typeid( TEnum );
161 }
162
163 /// Comparison operator with another \b Enum object.
164 /// The sort order is primarily determined by the enum types that were boxed.
165 /// If those are the same, then the underlying integral value of the enum elements is compared.
166 ///
167 /// This leads to a nested sort order, with the type information being the outer order and
168 /// the integral value of the enum being the inner one.
169 ///
170 /// \note
171 /// It is a matter of the compiler how the outer sort of types is performed and thus this
172 /// cannot be determined by the user code.
173 ///
174 ///
175 /// @param rhs The right-hand side argument of the comparison.
176 /// @return If the encapsulated type of this instance is the same as that of \p{rhs}, this
177 /// methods returns \c true if #Integral() of this object is smaller than the one of
178 /// \p{rhs} and otherwise \c false. If the types are not the same, than the result is
179 /// dependent on the tool chain (compiler) used for compiling \alib.
180 bool operator< (Enum const& rhs) const {
181 return ( std::type_index( TypeID() )
182 < std::type_index(rhs.TypeID() ) )
183 || ( TypeID() == rhs.TypeID()
184 && Integral() < rhs.Integral() );
185 }
186
187}; // class Enum
188
189} // namespace alib[::boxing]
190
191/// Type alias in namespace \b alib.
193
194} // namespace [alib]
Placeholder data
The data that we encapsulate.
Definition box.inl:40
bool IsType() const
TValue Unbox() const
Definition box.inl:595
const std::type_info & TypeID() const
Definition box.inl:780
Box() noexcept
Definition box.inl:224
ALIB_DLL size_t Hashcode() const
#define ALIB_EXPORT
Definition alib.inl:497
lang::integer integer
Type alias in namespace alib.
Definition integers.inl:149
boxing::Enum Enum
Type alias in namespace alib.
Definition enum.inl:192
bool operator==(TEnum rhs) const
Definition enum.inl:146
bool operator==(const Enum &rhs) const
Definition enum.inl:92
integer Integral() const
Definition enum.inl:86
const Box & CastToBox() const
Definition enum.inl:125
bool operator<(Enum const &rhs) const
Definition enum.inl:180
Box & CastToBox()
Definition enum.inl:119
constexpr Enum(TEnum element)
Definition enum.inl:62
Enum()
Default constructor.
Definition enum.inl:53
const std::type_info & TypeID() const
Definition box.inl:780
bool IsEnumType() const
Definition enum.inl:137
bool operator!=(const Enum &rhs) const
Definition enum.inl:98
bool operator!=(TEnum rhs) const
Definition enum.inl:158
TEnum Get() const
Definition enum.inl:75