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