ALib C++ Library
Library Version: 2402 R1
Documentation generated by doxygen
Loading...
Searching...
No Matches
enum.hpp
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-2024 A-Worx GmbH, Germany.
6 * Published under \ref mainpage_license "Boost Software License".
7 **************************************************************************************************/
8#ifndef HPP_ALIB_BOXING_ENUM
9#define HPP_ALIB_BOXING_ENUM 1
10
11#ifndef HPP_ALIB_BOXING_BOXING
12# include "alib/boxing/boxing.hpp"
13#endif
14
15#if ALIB_ENUMS && !defined (HPP_ALIB_ENUMS_RECORDS)
16# include "alib/enums/records.hpp"
17#endif
18
19#if !defined (_GLIBCXX_TYPEINDEX) && !defined(_TYPEINDEX_)
20# include <typeindex>
21#endif
22
23namespace alib { namespace boxing {
24
25/** ************************************************************************************************
26 * This class is useful to pass and accept enum values of arbitrary C++ scoped enum types.
27 * Based on class \alib{boxing;Box}, all interface is inherited, including type guessing and
28 * unboxing.
29 *
30 * In the constructor, enum elements of arbitrary type are accepted.
31 * The element's underlying integral value is boxed and thus run-time type-information is added.
32 * Having the "original" element stored in protected base class \b Box, has the following
33 * advantages:
34 *
35 * \note
36 * The implementation of this class by deriving from class \b Box, introduces a
37 * small memory overhead (usually 8 bytes per instance on 64-bit system), in respect to a
38 * possible alternative "direct" implementation. This is due to the fact that boxing allows
39 * one dimensional array types to be boxed as well as scalar types - which is never the case
40 * with this class.<br>
41 * But the advantages of doing so certainly surpass this small drawback.
42 *
43 * \note
44 * Class \b Box is inherited \c protected instead of public, to hide bigger portions of
45 * the base class's interface. While some functions are explicitly made visible with
46 * keyword \c using, for others, instances of this class have to be cased using
47 * overloaded methods #CastToBox.
48 *
49 * ## Functors In Namespace std ##
50 * Functors <c>std::hash</c>, <c>std::equal_to</c> and <c>std::less</c> are specialized for
51 * this type with the inclusion of header file \alibheader{compatibility/std_boxing_functional.hpp}
52 * as documented with namespace #alib::compatibility::std.
53 *
54 * ## Friends ##
55 * class \alib{boxing;Box}
56 **************************************************************************************************/
57struct Enum : protected Box
58{
59 #if !defined(ALIB_DOX)
60 friend class Box;
61 #endif
62
63 /** ********************************************************************************************
64 * Default constructor.
65 **********************************************************************************************/
67 : Box(nullptr)
68 {}
69
70 #if defined(ALIB_DOX)
71 /** ********************************************************************************************
72 * Implicit constructor which accepts arbitrary elements of scoped or non-scoped enum types.
73 *
74 * @tparam TEnum The external (user specific) enumeration type.
75 * @tparam TEnableIf Selects this constructor only for enum types. Must not be specified
76 * (deduced by the compiler).
77 * @param element The external (user specific) enumeration element.
78 **********************************************************************************************/
79 template<typename TEnum, typename TEnableIf>
80 inline
81 constexpr Enum( TEnum element );
82 #else
83 template<typename TEnum,
84 typename TEnableIf = typename std::enable_if<std::is_enum<TEnum>::value>::type >
85 constexpr Enum( TEnum element )
86 : Box( element ) {}
87 #endif
88
89 #if defined(ALIB_DOX)
90 /** ********************************************************************************************
91 * This is a shortcut to \alib{boxing;Box::Unbox;Box::Unbox<TEnum>()} to retrieve the
92 * original enum element in a type-safe way.
93 *
94 * Prior to invoking this, the boxed type can be checked with #IsType. If the wrong type
95 * is tried to be received, an \alib assertion is raised.
96 *
97 * @tparam TEnum The external (user specific) enumeration type.
98 * @return The underlying integral value of the encapsulated enum element.
99 **********************************************************************************************/
100 template<typename TEnum>
101 inline
102 TEnum Get() const;
103 #else
104 template<typename TEnum>
105 ATMP_T_IF(TEnum, std::is_enum<TEnum>::value )
106 Get() const
107 {
108 return Unbox<TEnum>();
109 }
110 #endif
111
112 /** ********************************************************************************************
113 * Returns the underlying integral value of the original enum element casted to type
114 * \alib{integer}.
115 *
116 * \note
117 * Boxed enum element values are always
118 * \ref alib_boxing_enums_integer "stored as type integer", regardless of the
119 * underlying type of the enumeration.
120 *
121 * @return The underlying integral value.
122 **********************************************************************************************/
124 {
125 return data.Integrals.Int;
126 }
127
128 /** ********************************************************************************************
129 * Comparison operator.
130 *
131 * @param rhs The right hand side argument of the comparison.
132 * @return \c true if this object equals \p{rhs}, \c false otherwise.
133 **********************************************************************************************/
134 bool operator==(const Enum& rhs) const
135 {
136 return this->CastToBox() == rhs.CastToBox();
137 }
138
139 /** ********************************************************************************************
140 * Comparison operator.
141 *
142 * @param rhs The right hand side argument of the comparison.
143 * @return \c true if this object does not equal \p{rhs}, \c false otherwise.
144 **********************************************************************************************/
145 bool operator!=(const Enum& rhs) const
146 {
147 return this->CastToBox() != rhs.CastToBox();
148 }
149
150 #if defined(ALIB_DOX)
151 /** ********************************************************************************************
152 * Imports \c protected base class's method \alib{boxing;Box::TypeID}.
153 * @return The \c std::type_info of the mapped \c enum type.
154 **********************************************************************************************/
155 using Box::TypeID;
156
157 /** ********************************************************************************************
158 * Imports \c protected base class's method \alib{boxing;Box::Hashcode}.
159 * @return A hashcode for the boxed enum type and value.
160 **********************************************************************************************/
161 using Box::Hashcode;
162 #else
163 using Box::TypeID;
164 using Box::Hashcode;
165 #endif
166
167 /** ********************************************************************************************
168 * This method casts an instance of this class to a reference of base class \b Box.
169 * To hide the bases class's interface, this class inherits class \b Box only as
170 * a \c protected base. With this method, this "artificial limitation " (its a design decision)
171 * is lifted.
172 *
173 * @return A mutable reference to this object.
174 **********************************************************************************************/
176 {
177 return static_cast<Box&>(*this);
178 }
179
180 /** ********************************************************************************************
181 * Same as overloaded version, but returns a \c const reference and consequently this method
182 * is declared\c const itself.
183 *
184 * @return A constant reference to this object.
185 **********************************************************************************************/
186 const Box& CastToBox() const
187 {
188 return static_cast<const Box&>(*this);
189 }
190
191
192 #if defined(ALIB_DOX)
193 /** ********************************************************************************************
194 * Checks if this instance has an enum element of type \p{TEnum} stored.<br>
195 * This method is an inlined, simple alias for \c protected base class's method
196 * \alib{boxing;Box::IsType}.
197 *
198 *
199 * @tparam TEnum The external (user specific) enumeration type.
200 * @return \c true if the encapsulated enum type of type \p{TEnum}, otherwise \c false.
201 **********************************************************************************************/
202 template<typename TEnum>
203 inline
204 bool IsEnumType() const;
205 #else
206 template<typename TEnum>
207 ATMP_T_IF(bool, std::is_enum<TEnum>::value)
208 IsEnumType() const
209 {
210 return Box::IsType<TEnum>();
211 }
212 #endif
213
214 #if defined(ALIB_DOX)
215 /** ********************************************************************************************
216 * Comparison operator with enum elements.
217 *
218 * @tparam TEnum The external (user specific) enumeration type.
219 * @param rhs The right hand side argument of the comparison.
220 * @return \c true if this object equals \p{rhs}, \c false otherwise.
221 **********************************************************************************************/
222 template<typename TEnum>
223 inline
224 bool operator==(TEnum rhs) const;
225 #else
226 template<typename TEnum>
227 ATMP_T_IF(bool, std::is_enum<TEnum>::value)
228 operator==(TEnum rhs) const
229 {
230 return Integral() == static_cast<typename std::underlying_type<TEnum>::type>( rhs )
231 && TypeID() == typeid( TEnum );
232 }
233 #endif
234
235 #if defined(ALIB_DOX)
236 /** ********************************************************************************************
237 * Comparison operator with enum elements.
238 *
239 * @tparam TEnum The external (user specific) enumeration type.
240 * @param rhs The right hand side argument of the comparison.
241 * @return \c true if this object does not equal \p{rhs}, \c false otherwise.
242 **********************************************************************************************/
243 template<typename TEnum>
244 inline
245 bool operator!=(TEnum rhs) const;
246 #else
247 template<typename TEnum>
248 ATMP_T_IF(bool, std::is_enum<TEnum>::value)
249 operator!=(TEnum rhs) const
250 {
251 return Integral() != static_cast<typename std::underlying_type<TEnum>::type>( rhs )
252 || TypeID() != typeid( TEnum );
253 }
254 #endif
255
256
257 /** ********************************************************************************************
258 * Comparison operator with another \b Enum object.
259 * The sort order is primarily determined by the enum types that were boxed.
260 * If those are the same, then the underlying integral value of the enum elements is compared.
261 *
262 * This leads to a nested sort order, with the type information being the outer order and
263 * the integral value of the enum being the inner one.
264 *
265 * \note
266 * It is a matter of the compiler how the outer sort of types is performed and thus this
267 * can not be determined by the user code.
268 *
269 *
270 * @param rhs The right hand side argument of the comparison.
271 * @return If the encapsulated type of this instance is the same as that of \p{rhs}, this
272 * methods returns \c true if #Integral() of this object is smaller than the one of
273 * \p{rhs} and otherwise \c false. If the types are not the same, than the result is
274 * dependent on the tool chain (compiler) used for compiling \alib.
275 **********************************************************************************************/
276 bool operator< (Enum const& rhs) const
277 {
278 return ( std::type_index( TypeID() )
279 < std::type_index(rhs.TypeID() ) )
280 || ( TypeID() == rhs.TypeID()
281 && Integral() < rhs.Integral() );
282 }
283
284 #if ALIB_ENUMS
285
286 /** ****************************************************************************************
287 * Returns the \ref alib_enums_records "ALib Enum Record" associated with this enumeration
288 * element.<br>
289 * In debug-compilations an \alib assertion is raised, if no enum record was defined for
290 * the enumeration element represented by this instance.
291 *
292 * \see
293 * - Namespace function \alib{enums::GetRecord} of module \alib_enums, which provides the
294 * standard way of accessing enum records for enum elements known at compile-time.
295 * - Sibling method #TryRecord.
296 *
297 * @tparam TRecord The enumeration record type associated with the enum type.
298 * This has to be explicitly provided.
299 * It is the caller's obligation to ensure that the requested type equals
300 * the one associated. Otherwise this method produces undefined behavior.
301 *
302 * @return The record that is associated with this enumeration element.
303 ******************************************************************************************/
304 template<typename TRecord>
305 const TRecord& GetRecord()
306 {
308 #if ALIB_STRINGS
309 ALIB_ASSERT_ERROR( result != nullptr, "BOXING",
310 NString128() << "Enum Record for type <" << lang::DbgTypeDemangler(TypeID()).Get()
311 << ">(" << Integral() << ") not found." )
312 #else
313 ALIB_ASSERT_ERROR( result != nullptr,
314 "BOXING: Enum Record for type not found: ",
315 DbgTypeDemangler(TypeID()).Get() )
316 #endif
317
318
319 return *reinterpret_cast<const TRecord*>( result );
320 }
321
322 /** ****************************************************************************************
323 * Returns a pointer to the \ref alib_enums_records "ALib Enum Record" associated with this
324 * the enumeration element represented by this instance.
325 * If no enum record was is defined, \c nullptr is returned.
326 *
327 * \see
328 * - Namespace function \alib{enums::TryRecord} of module \alib_enums, which provides the
329 * standard way of accessing enum records for enum elements known at compile-time.
330 * - Sibling method #GetRecord.
331 *
332 * @tparam TRecord The enumeration record type associated with the enum type.
333 * This has to be explicitly provided.
334 * It is the caller's obligation to ensure that the requested type equals
335 * the one associated. Otherwise this method produces undefined behavior.
336 *
337 * @return A pointer to the record that is associated with this enumeration element,
338 * respectively \c nullptr if no record was found.
339 ******************************************************************************************/
340 template<typename TRecord>
341 const TRecord* TryRecord()
342 {
343 return reinterpret_cast<const TRecord*>( enums::detail::getEnumRecord( TypeID(), Integral() ) );
344 }
345
346 #endif // ALIB_ENUMS
347
348}; // class Enum
349
350} // namespace alib[::boxing]
351
352/// Type alias in namespace \b alib.
354
355} // namespace [alib]
356
357// #################################################################################################
358// T_Append<Enum>
359// #################################################################################################
360#if ALIB_STRINGS
361
362 #if !defined (HPP_ALIB_STRINGS_ASTRING)
363 # include "alib/strings/astring.hpp"
364 #endif
365
366
367 namespace alib { namespace strings {
368 // Faking all template specializations of namespace strings for doxygen into namespace
369 // strings::APPENDABLES to keep the documentation of namespace string clean!
370 #if defined(ALIB_DOX)
371 namespace APPENDABLES {
372 #endif
373
374 /**
375 * Specialization of functor \alib{strings;T_Append} for type \alib{boxing;Enum}.
376 */
377 template<typename TChar> struct T_Append<boxing::Enum, TChar>
378 {
379 /** ************************************************************************************
380 * Writes the given boxed object. This is done by invoking box-function
381 * \alib{boxing;FAppend} on box \p{value}.
382 *
383 * @param target The \b AString that \b Append was invoked on.
384 * @param value The enum-box to its contents to \p{target}.
385 **************************************************************************************/
386 void operator()( TAString<TChar>& target, const boxing::Enum& value )
387 {
388 value.CastToBox().Call<boxing::FAppend<TChar>>( target );
389 }
390
391 };
392
393 #if defined(ALIB_DOX)
394 } // namespace alib::strings[::appendables]
395 #endif
396 }} // namespace [alib::strings]
397
398#endif // ALIB_STRINGS
399
400
401#endif // HPP_ALIB_BOXING_ENUM
ALIB_API size_t Hashcode() const
Definition boxing.cpp:195
Placeholder data
Definition box.inl:51
decltype(std::declval< typename TFDecl::Signature >()(std::declval< Box & >(), std::declval< TArgs >()...)) Call(TArgs &&... args) const
Definition box.inl:1135
const std::type_info & TypeID() const
Definition box.inl:902
bool IsArrayOf() const
Definition box.inl:724
#define ALIB_ASSERT_ERROR(cond,...)
Definition alib.hpp:984
#define ATMP_T_IF(T, Cond)
Definition tmp.hpp:53
ALIB_API const void * getEnumRecord(const std::type_info &rtti, integer integral)
Definition records.cpp:60
Definition alib.cpp:57
NLocalString< 128 > NString128
Type alias name for TLocalString<nchar,128> .
lang::integer integer
Type alias in namespace alib.
Definition integers.hpp:286
constexpr Enum(TEnum element)
integer Integral() const
Definition enum.hpp:123
bool operator<(Enum const &rhs) const
Definition enum.hpp:276
const TRecord & GetRecord()
Definition enum.hpp:305
const TRecord * TryRecord()
Definition enum.hpp:341
TEnum Get() const
const Box & CastToBox() const
Definition enum.hpp:186
bool operator==(const Enum &rhs) const
Definition enum.hpp:134
Box & CastToBox()
Definition enum.hpp:175
bool operator==(TEnum rhs) const
bool operator!=(TEnum rhs) const
bool operator!=(const Enum &rhs) const
Definition enum.hpp:145
const std::type_info & TypeID() const
Definition box.inl:902
bool IsEnumType() const
void operator()(TAString< TChar > &target, const boxing::Enum &value)
Definition enum.hpp:386
detail::UnionIntegrals Integrals
Collection of integrals of different sizes.
integer Int
Signed integral of platform-dependent size.