ALib C++ Framework
by
Library Version: 2605 R0
Documentation generated by doxygen
Loading...
Searching...
No Matches
functiondecls.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/// Copyright 2013-2026 A-Worx GmbH, Germany.
6/// Published under #"mainpage_license".
7//==================================================================================================
8
9ALIB_EXPORT namespace alib { namespace boxing {
10class Box;
11
12//==================================================================================================
13/// This built-in #"alib_boxing_functions;box function" constitutes the concept of
14/// "nullable types". Nullable types are pointer types, array types and custom types that are
15/// nullable. Arithmetical types are never \e nulled, even if they contain value \c 0 or \c 0.0.
16///
17/// A default implementation is given, which returns \c false (not <em>nulled</em>!) if the first word in
18/// the placeholder is not \c 0. Hence this works for array and pointer types.
19///
20/// A constant function return \c true is given with the static method #"ConstantTrue". This function
21/// is set as the specific implementation for all arithmetical types, as well as for type \c bool.
22///
23/// \note
24/// The reason why this function is not declared as \b FIsNull, but instead is negated, is that
25/// if any function is called on a #"alib_boxing_more_void_void;void box", a
26/// default value is returned. The default value of \c bool is \c false, which probably better
27/// fits - even if conceptually a void box is undefined and therefore neither \e nulled or not.
28//==================================================================================================
29struct FIsNotNull {
30 /// Signature of the invokable function.
31 ///
32 /// @param self The box that the function was invoked on.
33 /// @return Return \c false if a boxed value is \e nulled, \c true otherwise.
34 using Signature = bool (*) ( const Box& self );
35
36 /// This implementation of the function signature returns constant \c true.
37 /// It may be registered with custom types that do not provide the concept of being \e nulled.
38 /// #"alib_mod_bs;Bootstrapping" function
39 /// #"boxing::bootstrap" registers this implementation with type \c bool and all integral,
40 /// floating point and character types.
41 ///
42 /// @return Constant \c true.
44 static bool ConstantTrue( const Box& );
45};
46
47
48//==================================================================================================
49/// This function returns a hashcode on contents of the box. This is useful if boxes are to
50/// be used as key-values of containers like \c std::unordered_map or
51/// #"HashTable".
52///
53/// Its default implementation creates a hash code using the raw placeholder values and
54/// in case of array types over the array memory used.
55///
56/// A templated version that compares the first N-bytes is given with #"UsePlaceholderBytes".
57/// Because the number of bytes to use are given with the template parameter, the method compiles
58/// to shortest code. It is registered with all fundamental types.
59///
60/// \note
61/// Compatibility header #"F;ALib.Boxing.StdFunctors.H" specializes
62/// functors \c std::hash, \c std::equal_to and \c std::less for use with containers of the
63/// C++ standard library.
64///
65/// \see
66/// Method #"Box::Hashcode", which calls this function.
67//==================================================================================================
68struct FHashcode {
69 /// Signature of the invokable function.
70 ///
71 /// @param self The box that the hash code is to be calculated for.
72 /// @return The hash code.
73 using Signature = size_t (*) ( const Box& self );
74
75 /// Templated hash function usable with types boxed as values.
76 /// For pointer types, a custom variant that collects type-specific hashable data is recommended.
77 ///
78 /// @tparam N The number of bytes to check.
79 /// @param self The box to calculate a hash code for.
80 /// @return The hash code.
81 template<size_t N>
82 static size_t UsePlaceholderBytes( const Box& self );
83
84};
85
86
87//==================================================================================================
88/// This function compares two boxes.
89///
90/// A default implementation is #"BootstrapRegisterDefault;registered" that compares the types
91/// (#"Box::IsSameType") and if equal, with arrays compares the array's length,
92/// \e nulled state and finally the contents using \c memcmp.<br>
93/// For non-array types, it compares the relevant bytes in the placeholder.
94/// The number of leading relevant bytes is available with method
95/// #"Box::GetPlaceholderUsageLength".
96///
97/// Type-specific implementations are given and registered for fundamental types. Integrals
98/// of different sizes and floating point values will be compared by using
99/// #"Box::UnboxSignedIntegral", #"Box::UnboxUnsignedIntegral" and
100/// #"Box::UnboxFloatingPoint" and appropriate casting.
101/// In the case of floating point comparison, an epsilon distance is duly taken into account.
102///
103/// For custom types, with #".ComparableTypes", a templated implementation is suggested: Rather than
104/// implementing a specific box-function, the custom type should implement \c operator== and register
105/// an instantiation of the templated function.
106///
107/// \see
108/// Method #"Box::operator==", which calls this function.
109//==================================================================================================
110struct FEquals {
111 /// Signature of the invokable function.
112 ///
113 /// @param self The box that the function was invoked on.
114 /// @param rhs The box to compare.
115 /// @return Return value and type is implementation specific.
116 using Signature = bool (*) ( const Box& self, const Box& rhs);
117
118
119 #if DOXYGEN
120 /// Templated implementation of the function signature, usable with boxable types which have
121 /// <c>operator==</c> implemented.
122 ///
123 /// \note
124 /// This method internally is provided twice: once for types boxed as pointers and one for
125 /// types boxed as values, and selected using keyword \c requires.<br>
126 /// If a type is boxed as a pointer, then \p{TComparable} has to be given as such
127 /// pointer-type.
128 /// For comparison, the unboxed pointers will be dereferenced.
129 /// If one is \e nulled, \c false is returned, if both are \e nulled, true.
130 ///
131 /// \see
132 /// Macro #"ALIB_BOXING_DEFINE_FEQUALS_FOR_COMPARABLE_TYPE".
133 ///
134 /// @tparam TComparable The mapped type that can be compared using <c>operator==</c>.
135 /// @param self The box that the function was invoked on.
136 /// @param rhs The boxed value to compare.
137 ///
138 /// @return \c true if \p{self} equals \p{rhs}, \c false otherwise.
139 template<typename TComparable>
140 static
141 bool ComparableTypes( const Box& self, const Box& rhs );
142
143 #else
144 template<typename TComparable>
145 requires (!std::is_pointer_v<TComparable> )
146 static bool ComparableTypes( const Box& self, const Box& rhs );
147
148 template<typename TComparable>
149 requires (std::is_pointer_v<TComparable>)
150 static bool ComparableTypes( const Box& self, const Box& rhs );
151 #endif
152};
153
154
155//==================================================================================================
156/// This function provides a relational comparison of two boxes.
157///
158/// A default implementation is #"BootstrapRegisterDefault;registered" that compares the types.
159/// If they are equal, the first \c uinteger values in the placeholders are compared.
160/// Specifics for array types are \b not implemented with that default version.
161///
162/// If the types are not the same, the result of the comparison of the runtime type information
163/// object is returned. For this, method #"Box::TypeID" is invoked on both boxes
164/// and to allow <c>operator<</c> on those, \c std::type_index is applied.
165/// This leads to a "nested" sort order, with the type information being the outer order and
166/// the boxed data being the inner.<br>
167/// To keep this overall order intact, type-specific implementations should use the following
168/// implementation scheme:
169///
170/// if( rhs.IsType<AComparableType1>() )
171/// return MyCompare( self.Unbox<MyType>, rhs.Unbox<AComparableType1>();
172///
173/// if( rhs.IsType<AComparableType2>() )
174/// return MyCompare( self.Unbox<MyType>, rhs.Unbox<AComparableType2>();
175///
176/// if( ...
177/// return ...
178///
179/// return std::type_index( self.TypeID() ) < std::type_index( rhs.TypeID() );
180///
181/// With this scheme in place, for example, \c std::sort will work properly on containers of boxes of
182/// mixed types. The following sample demonstrates this. It uses a specialization of
183/// \c std::less<T> for type #"%Box". This is found in a compatibility header:
184///
185/// \snippet "DOX_BOXING.cpp" DOX_BOXING_FISLESS_INCLUDES
186///
187/// With that, the following code compiles fine:
188/// \snippet "DOX_BOXING.cpp" DOX_BOXING_FISLESS
189///
190/// It generates the following output:
191///
192/// \snippet "DOX_BOXING_FISLESS.txt" OUTPUT
193///
194/// As can be seen from the result, a proper "outer" sorting is in place. Nevertheless,
195/// floating-point and integral values follow the inner sorting.
196/// This is because specific implementations of the functions are registered for all arithmetic
197/// types, which allow comparisons of mixed types.
198/// The same is true for the different C++ character types.
199///
200/// \note
201/// It is a matter of the compiler (and cannot be determined by the user code) how the
202/// types are sorted (outer sorting).<br>
203/// Furthermore, the default implementation that simply compares the first #"%lang::uinteger" of
204/// the placeholder is unlikely to produce "reasonable" results.
205///
206/// Type-specific implementations are given and registered for fundamental types. Integrals
207/// of different sizes and floating point values will be compared by using
208/// #"Box::UnboxSignedIntegral", #"Box::UnboxUnsignedIntegral" and
209/// #"Box::UnboxFloatingPoint" and appropriate casting.
210///
211/// If module \alib_strings is included in the \alibbuild, an implementation for
212/// arrays of #"characters::nchar", #"characters::wchar" and #"characters::xchar" is given.
213///
214/// For custom types, with #".ComparableTypes", a templated implementation is suggested: Rather than
215/// implementing a specific box-function, the custom type should implement \c operator< and register
216/// an instantiation of the templated function.
217///
218/// \see
219/// Method #"Box::operator<", which calls this function.
220//==================================================================================================
221struct FIsLess {
222 /// Signature of the invokable function.
223 ///
224 /// @param self The box that the function was invoked on.
225 /// @param rhs The box to compare.
226 /// @return Return value and type is implementation specific.
227 using Signature = bool (*) ( const Box& self, const Box& rhs);
228
229
230 #if DOXYGEN
231 /// Templated implementation for function #"FIsLess", usable with boxable types
232 /// which have <c>operator<</c> implemented.
233 ///
234 /// \note
235 /// This method internally is provided twice, once for types boxed as pointers and one for
236 /// types boxed as values, and selected using template programming.<br>
237 /// If a type is boxed as pointer, then \p{TComparable} has to be given as such a pointer
238 /// type.
239 /// For comparison, the unboxed pointers will be dereferenced. If both are \e nulled, \c false
240 /// is returned if only \p{self} is \e nulled, \c true and if only \p{rhs} is \e nulled,
241 /// then \c false.
242 ///
243 /// \see
244 /// Macro #"ALIB_BOXING_DEFINE_FISLESS_FOR_COMPARABLE_TYPE".
245 ///
246 /// @tparam TComparable The mapped type that can be compared using <c>operator<</c>.
247 /// @param self The box that the function was invoked on.
248 /// @param rhs The boxed value to compare.
249 ///
250 /// @return \c true if \p{self} equals \p{rhs}, \c false otherwise.
251 template<typename TComparable>
252 static
253 bool ComparableTypes( const Box& self, const Box& rhs );
254
255 #else
256 template<typename TComparable>
257 requires (!std::is_pointer_v<TComparable> )
258 static bool ComparableTypes( const Box& self, const Box& rhs );
259
260 template<typename TComparable>
261 requires (std::is_pointer_v<TComparable> )
262 static bool ComparableTypes( const Box& self, const Box& rhs );
263 #endif
264};
265
266
267#if ALIB_MONOMEM
268
269//==================================================================================================
270/// This type declares a built-in #"alib_boxing_functions;box-function".<br>
271/// Besides mandatory parameter \p{self}, implementations expect a reference to an allocator of type
272/// #"MonoAllocator". With that, a deep copy of the boxed object can be allocated.
273///
274/// The function is provided for use-cases where boxes have to "survive" the end of
275/// the life-cycle of the original object.
276///
277/// A default implementation of this function is provided. While this just does nothing
278/// for non-array types, with array types, the complete contents of the array is cloned.
279/// With this in place, all boxed character arrays (strings) are cloned.
280/// This is done regardless if it is necessary or not. For example, if the boxed string
281/// was created from a C++ string literal, a deep copy is unnecessary.
282/// While this imposes a little overhead, there is no way to avoid this because the origin of a
283/// boxed array cannot be determined.
284///
285/// \attention
286/// Only objects that do not need to be destructed are allowed to be cloned using the
287/// monotonic allocator given. This is because \b no destructor will be invoked for boxed objects
288/// (which is true in general for \alib_boxing).<br>
289/// Of course a custom implementation could create and allocate the object in a custom place,
290/// that allows later destruction. Alternatively, a custom method could just ensure that
291/// an object will not be deleted, e.g., by increasing a usage counter and leave the given box
292/// untouched.
293///
294/// \note
295/// Today, this is the only box-function type found within \alib, that requires a
296/// mutable "this" pointer (aka a non constant parameter \p{self}).<br>
297/// Consequently, if the function is called, the compiler selects the non-constant version of
298/// method #"Box::Call".<br>
299/// Furthermore it has to be noted, that an invocation of this function might change the type
300/// together with the contents of \p{self}. Therefore, results of any already performed
301/// type-guessing are not valid after an invocation.
302///
303/// \attention
304/// If a mapped type has no specialization for this function, there are three possibilities:
305/// 1. The original value is not deleted during the life-cycle of the box.
306/// 2. The type was boxed as a value type (or, very unlikely, otherwise is safe to be unboxed,
307/// even after the deletion of the original value).
308/// 3. Undefined behavior (crash) due to unboxing the value after deletion of the original
309/// object.
310///
311/// \par Availability
312/// This box-function is available only if the module \alib_monomem is included in the
313/// \alibbuild.
314//==================================================================================================
315struct FClone {
316 /// Signature of the box-function.
317 ///
318 /// @param self The mutable box that the function was invoked on.
319 /// @param allocator A monotonic allocator that may be used for cloning.
320 using Signature = void (*) ( boxing::Box& self, MonoAllocator& allocator );
321};
322#endif
323
324//==================================================================================================
325/// This is one of the built-in #"alib_boxing_functions;box-functions" of \alib_boxing_nl.
326/// This function is used to give an answer to the question if a boxed value represents a boolean
327/// value \c true or \c false. This is useful if "yes/no" decisions should be taken based on
328/// arbitrary boxed values.
329///
330/// A default implementation is registered which for non-array types just interprets the first
331/// integral value in the #"boxing::Placeholder": If it is not \c 0, \c true is returned, \c false
332/// otherwise.<br>
333/// For array types, the default implementation returns \c true if method
334/// #"Box::UnboxLength" returns a value different to \c 0, otherwise \c false is returned.
335//==================================================================================================
336struct FIsTrue {
337 /// Signature of the invokable function.
338 ///
339 /// @param self The box that the function was invoked on.
340 /// @return Return value and type is implementation specific.
341 using Signature = bool (*) ( const Box& self);
342};
343
344
345#if ALIB_STRINGS
346//==================================================================================================
347/// Implementations of this #"alib_boxing_functions;box-function" write the content of the
348/// data stored in the box to the given #"%AString" object.
349///
350/// A default implementation is registered. This writes out the raw value of the first
351/// \c uinteger field of the boxes' #"boxing::Placeholder" in hexadecimal format.
352/// For pointer types, such raw value reflects the memory address of the boxable.
353/// In debug-compilations, in addition, the type name of the boxed value is written.
354///
355/// Templated static method #".Appendable" can be used to avoid implementations for those mapped types
356/// that specialized type-traits functor #"AppendableTraits" that makes values of the type
357/// usable with #"TAString::Append(const TAppendable&)" already.
358///
359/// \note
360/// This is a templated (!) function declaration that defines three different box-functions at
361/// once, namely \b FAppend<character>, \b FAppend<characters::complementChar> and
362/// \b FAppend<strangeChar>.
363///
364/// This box-function is usually invoked only indirectly, by "appending" a box to an #"%AString",
365/// as shown here:
366///
367/// Box box= 42;
368/// AString text;
369///
370/// text << "The answer is: "; // appends a string literal
371/// text << box; // translates to: box.Call<FAppend<character>>( text )
372///
373/// \par Availability
374/// This box-function is available only if the module \alib_strings is included in the \alibbuild.
375///
376/// \see
377/// - Manual chapter #"alib_boxing_strings_fappend"
378/// - Chapter #"alib_format_custom_types" of
379/// the Programmer's Manual of \alib_format, which gives
380/// a sample implementation of this function, and introduces a more powerful
381/// box-function #"FFormat".
382///
383/// @tparam TChar The character type of the destination #"^AString" given with parameter
384/// \p{target}.
385/// @tparam TAllocator The allocator type, as prototyped with class #"lang::Allocator".
386//==================================================================================================
387template<typename TChar, typename TAllocator>
388struct FAppend {
389 /// Signature of the invokable function.
390 ///
391 /// @param self The box that the function was invoked on.
392 /// @param target The target #"%AString" of character type \p{TChar}.
393 using Signature = void (*) ( const Box& self, strings::TAString<TChar, TAllocator>& target );
394
395
396 #if DOXYGEN
397 /// Static templated implementation of #"FAppend" for boxed types which are appendable.
398 ///
399 /// Once a type is made \e appendable by specializing type-traits functor
400 /// #"AppendableTraits", then this static templated function can be used "as is"
401 /// and registered with the corresponding mapped type.
402 ///
403 /// \note
404 /// This method internally is provided twice, once for types boxed as pointers and one for
405 /// types boxed as values, and selected using template programming.<br>
406 /// If a type is boxed as a pointer, then \p{TComparable} has to be given as such a pointer
407 /// type.
408 /// For comparison, the unboxed pointers will be dereferenced. This means that
409 /// it is believed that #"AppendableTraits" is specialized for the non-pointer type.
410 /// If this is not the case, then two options exist:
411 /// 1. Specialize functor #"AppendableTraits" for the non-pointer type in parallel.
412 /// 2. Do not use this inlined implementation, but rather provide a custom one that
413 /// does not dereference unboxed pointers.
414 ///
415 /// \see
416 /// Macros
417 /// - ALIB_BOXING_BOOTSTRAP_REGISTER_FAPPEND_FOR_APPENDABLE_TYPE
418 /// - ALIB_BOXING_BOOTSTRAP_REGISTER_FAPPEND_FOR_APPENDABLE_TYPE_N
419 /// - ALIB_BOXING_BOOTSTRAP_REGISTER_FAPPEND_FOR_APPENDABLE_TYPE_W
420 /// - ALIB_BOXING_BOOTSTRAP_REGISTER_FAPPEND_FOR_APPENDABLE_TYPE_X
421 ///
422 /// @tparam TAppendable The "appendable" mapped box type that the function is to be implemented
423 /// for.
424 /// @param self The box that the function was invoked on.
425 /// @param target The target #"%AString" of character type \p{TChar}.
426 template<typename TAppendable>
427 inline static
429 #else
430
431 template<typename TAppendable>
432 requires ( !std::is_pointer_v<TAppendable> )
433 static void Appendable( const Box& self, strings::TAString<TChar, TAllocator>& target );
434
435 template<typename TAppendable>
436 requires ( std::is_pointer_v<TAppendable> )
437 static void Appendable( const Box& self, strings::TAString<TChar, TAllocator>& target );
438
439 #endif
440
441
442 /// Implementation template for box-function #"FAppend" for appendable types wrapped
443 /// in \c std::reference_wrapper to
444 /// #"alib_boxing_customizing_identity;bypass custom boxing".
445 ///
446 /// This static function template can be used for any type \p{TAppendable} that has a
447 /// specialization of functor #"AppendableTraits" defined and that becomes boxed
448 /// in the wrapper type.
449 ///
450 /// @tparam TAppendable The "appendable" wrapped mapped box type that the function is to be
451 /// implemented for.
452 /// @param self The box that the function was invoked on.
453 /// @param target The target #"%AString" object.
454 template<typename TAppendable>
455 inline static
457}; // FAppend
458#endif //ALIB_STRINGS
459
460}
461
462/// Type alias in namespace #"%alib".
464
465#if ALIB_MONOMEM
466/// Type alias in namespace #"%alib".
468#endif
469
470/// Type alias in namespace #"%alib".
472
473/// Type alias in namespace #"%alib".
475
476/// Type alias in namespace #"%alib".
478
479/// Type alias in namespace #"%alib".
481
482#if ALIB_STRINGS
483/// Type alias in namespace #"%alib".
484template<typename TChar, typename TAllocator>
486#endif
487
488} // namespace [alib::boxing]
#define ALIB_DLL
#define ALIB_EXPORT
DOXYGEN.
Definition box.cpp:17
Definition alox.cpp:14
monomem::TMonoAllocator< lang::HeapAllocator > MonoAllocator
boxing::FHashcode FHashcode
Type alias in namespace #"%alib".
boxing::FIsLess FIsLess
Type alias in namespace #"%alib".
boxing::FIsNotNull FIsNotNull
Type alias in namespace #"%alib".
boxing::FClone FClone
Type alias in namespace #"%alib".
boxing::FIsTrue FIsTrue
Type alias in namespace #"%alib".
boxing::FEquals FEquals
Type alias in namespace #"%alib".
strings::Appendable< TAppendable > Appendable
Type alias in namespace #"%alib".
boxing::FAppend< TChar, TAllocator > FAppend
Type alias in namespace #"%alib".
static void Appendable(const Box &self, strings::TAString< TChar, TAllocator > &target)
void(*)(const Box &self, strings::TAString< TChar, TAllocator > &target) Signature
static void WrappedAppendable(const Box &self, strings::TAString< TChar, TAllocator > &target)
void(*)(boxing::Box &self, MonoAllocator &allocator) Signature
static bool ComparableTypes(const Box &self, const Box &rhs)
bool(*)(const Box &self, const Box &rhs) Signature
static size_t UsePlaceholderBytes(const Box &self)
size_t(*)(const Box &self) Signature
bool(*)(const Box &self, const Box &rhs) Signature
static bool ComparableTypes(const Box &self, const Box &rhs)
static bool ConstantTrue(const Box &)
Definition box.cpp:138
bool(*)(const Box &self) Signature
bool(*)(const Box &self) Signature