.. _utilities_file: ********************************** Utilities and Type Traits Overview ********************************** ``utilities.hpp`` provides foundational type traits, metaprogramming utilities, and core C++ utilities that serve as building blocks for more complex library components. The header is designed to be self-contained with minimal dependencies on the standard library, emphasizing clarity, correctness, and compile-time type safety. Design Philosophy ================== The utilities library follows these core principles: * **Self-Contained**: Minimal dependencies - only requires ```` and ```` * **Type-Safe**: Heavy use of SFINAE and template metaprogramming to catch errors at compile-time * **Zero Runtime Overhead**: All type traits and utilities are resolved at compile-time * **Standard-Compliant**: Closely mirrors C++ standard library type traits and utilities * **Educational**: Code is structured to be readable and demonstrate template metaprogramming techniques Library Components ================== Type Manipulation Utilities ____________________________ Reference Removal ~~~~~~~~~~~~~~~~~ ``RemoveRef`` removes reference qualifiers from a type. .. code-block:: cpp RemoveRef::type // int RemoveRef::type // int RemoveRef::type // int **Alias**: ``RemoveRefT`` provides convenient access to ``RemoveRef::type`` Type Query Traits _________________ IsLValueRef ~~~~~~~~~~~~~~ Detects whether a type is an lvalue reference. .. code-block:: cpp IsLValueRef::value // true IsLValueRef::value // false IsLValueRef::value // false IsSame ~~~~~~~~~~~~ Checks if two types are identical. .. code-block:: cpp IsSame::value // true IsSame::value // false IsSame::value // false IsArray ~~~~~~~~~~ Detects array types (both bounded and unbounded). .. code-block:: cpp IsArray::value // true IsArray::value // true IsArray::value // false IsArray::value // false Type Relationship Traits ________________________ IsConvertible ~~~~~~~~~~~~~~~~~~~~~~~ Determines if type ``From`` can be implicitly converted to type ``To``. .. code-block:: cpp IsConvertible::value // true IsConvertible::value // true IsConvertible::value // false **Implementation Note**: Uses the detection idiom with a helper function ``_accept()`` to test convertibility via overload resolution. IsConstructible ~~~~~~~~~~~~~~~~~~~~~~~~~~~ Checks if type ``T`` can be constructed from the given argument types. .. code-block:: cpp IsConstructible::value // true IsConstructible::value // true IsConstructible::value // true (default constructible) **Derived Traits**: * ``IsDefaultConstructible`` - Can ``T`` be default-constructed? * ``IsMoveConstructible`` - Can ``T`` be constructed from ``T&&``? * ``IsCopyConstructible`` - Can ``T`` be constructed from ``const T&``? IsAssignable ~~~~~~~~~~~~~~~~~~ Determines if an object of type ``T`` can be assigned a value of type ``U``. .. code-block:: cpp IsAssignable::value // true IsAssignable::value // false IsAssignable::value // false (not a reference) **Derived Traits**: * ``IsMoveAssignable`` - Can ``T&`` be assigned from ``T&&``? * ``IsCopyAssignable`` - Can ``T&`` be assigned from ``const T&``? Metaprogramming Utilities __________________________ BoolConstant ~~~~~~~~~~~~~~~ Wraps a compile-time boolean value in a type. .. code-block:: cpp BoolConstant::value // true BoolConstant::value // false **Aliases**: * ``TrueType`` - Alias for ``BoolConstant`` * ``FalseType`` - Alias for ``BoolConstant`` **Usage**: Commonly used for tag dispatch to select function overloads at compile-time. EnableIf ~~~~~~~~~~~~~~~~~ SFINAE helper that defines a member ``type`` only if the condition is true. .. code-block:: cpp // Only defines ::type if Cond is true EnableIf::type // int EnableIf::type // Does not exist (SFINAE) **Alias**: ``EnableIfT`` provides convenient access to ``EnableIf::type`` **Typical Usage**: .. code-block:: cpp template ::value>> void process(T value) { // Only enabled for integral types } VoidT ~~~~~~~~~~~~ Maps any sequence of types to ``void``. Used in detection idioms. .. code-block:: cpp VoidT // void **Typical Usage**: .. code-block:: cpp template struct HasTypedef : FalseType { }; template struct HasTypedef> : TrueType { }; Core Utility Functions ______________________ move() ~~~~~~ Casts an lvalue to an rvalue reference, enabling move semantics. .. code-block:: cpp template constexpr RemoveRefT&& move(T&& x) noexcept; **Usage**: .. code-block:: cpp std::string s1 = "hello"; std::string s2 = cslt::move(s1); // s1 is now in moved-from state forward() ~~~~~~~~~ Perfect forwarding utility that preserves value categories. .. code-block:: cpp template constexpr T&& forward(RemoveRefT& x) noexcept; template constexpr T&& forward(RemoveRefT&& x) noexcept; **Usage**: .. code-block:: cpp template void construct(T* ptr, Args&&... args) { new (ptr) T(cslt::forward(args)...); } swap() ~~~~~~ Exchanges the values of two objects. .. code-block:: cpp template constexpr void swap(T& a, T& b) noexcept; **Usage**: .. code-block:: cpp int x = 1, y = 2; cslt::swap(x, y); // x == 2, y == 1 declval() ~~~~~~~~~ Obtains a reference to a type without constructing an object. Used in unevaluated contexts. .. code-block:: cpp template T&& declval() noexcept; **Usage**: .. code-block:: cpp // Detect if T has a size() member function template using HasSize = decltype(declval().size()); Internal Implementation Details =============================== The library uses the ``detail`` namespace for implementation details that are not part of the public API but are documented here for completeness. Detection Idiom Helpers _______________________ IsConvertibleImpl ~~~~~~~~~~~~~~~~~~~~~~~~~~~ Implementation of ``IsConvertible`` using SFINAE and overload resolution: .. code-block:: cpp template struct IsConvertibleImpl { private: template (declval()))> static char test(int); template static long test(...); public: static constexpr bool value = (sizeof(test(0)) == sizeof(char)); }; IsConstructibleImpl ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Implementation of ``IsConstructible`` using direct construction syntax: .. code-block:: cpp template struct IsConstructibleImpl { private: template ()...))> static char test(int); template static long test(...); public: static constexpr bool value = (sizeof(test(0)) == sizeof(char)); }; IsAssignableImpl ~~~~~~~~~~~~~~~~~~~~~~ Implementation of ``IsAssignable`` testing assignment expression validity: .. code-block:: cpp template struct IsAssignableImpl { private: template () = declval())> static char test(int); template static long test(...); public: static constexpr bool value = (sizeof(test(0)) == sizeof(char)); }; Reference Counting Primitives ______________________________ Control Block Structure ~~~~~~~~~~~~~~~~~~~~~~~ .. code-block:: cpp struct ControlBlock { std::atomic strong; // Strong reference count std::atomic weak; // Weak reference count ControlBlock() : strong(1u), weak(1u) {} virtual ~ControlBlock() {} virtual void destroy_object() noexcept = 0; virtual void* get_ptr() const noexcept = 0; }; The control block is used by smart pointers for thread-safe reference counting. It maintains separate counters for strong (owning) and weak (observing) references. ControlBlockPtr ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Concrete control block that stores a pointer and custom deleter: .. code-block:: cpp template struct ControlBlockPtr final : ControlBlock { T* ptr; Deleter del; void destroy_object() noexcept override { if (ptr) { del(ptr); ptr = nullptr; } } }; Reference Counting Functions ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Thread-safe atomic reference counting operations: **Strong Reference Operations**: * ``incref_strong(ControlBlock*)`` - Atomically increment strong count * ``decref_strong(ControlBlock*)`` - Atomically decrement strong count, returns true if reached zero * ``get_strong_count(const ControlBlock*)`` - Read current strong count **Weak Reference Operations**: * ``incref_weak(ControlBlock*)`` - Atomically increment weak count * ``decref_weak(ControlBlock*)`` - Atomically decrement weak count, returns true if reached zero * ``get_weak_count(const ControlBlock*)`` - Read current weak count * ``try_incref_strong(ControlBlock*)`` - Atomically try to promote weak to strong reference **Memory Ordering**: Uses ``memory_order_relaxed`` for increments and ``memory_order_acq_rel`` for decrements to ensure proper synchronization without unnecessary overhead. Requirements ============ Compiler Support ________________ * C++11 or later * Support for variadic templates * Support for template aliases (``using`` syntax) * Support for ``constexpr`` functions * Support for ``noexcept`` specifications * Support for ``std::atomic`` (C++11) Dependencies ____________ * ```` - For ``size_t`` and ``nullptr_t`` * ```` - For thread-safe reference counting primitives Usage Examples ============== Type Trait Queries __________________ .. code-block:: cpp #include "utilities.hpp" struct Base { }; struct Derived : Base { }; static_assert(cslt::IsConvertible::value, ""); static_assert(!cslt::IsConvertible::value, ""); static_assert(cslt::IsSame::value, ""); static_assert(!cslt::IsSame::value, ""); SFINAE with EnableIf _____________________ .. code-block:: cpp #include "utilities.hpp" // Only enabled for integral types template cslt::EnableIfT::value, T> double_value(T x) { return x * 2; } // Only enabled for floating-point types template cslt::EnableIfT::value, T> double_value(T x) { return x * 2.0; } Perfect Forwarding __________________ .. code-block:: cpp #include "utilities.hpp" template T* construct_at(T* ptr, Args&&... args) { return new (ptr) T(cslt::forward(args)...); } int main() { alignas(std::string) char buffer[sizeof(std::string)]; std::string* str = construct_at( reinterpret_cast(buffer), "hello world" ); str->~string(); } Tag Dispatch Pattern ____________________ .. code-block:: cpp #include "utilities.hpp" template void process_impl(T value, cslt::TrueType /* is_pointer */) { // Implementation for pointer types if (value) { // Dereference and process } } template void process_impl(T value, cslt::FalseType /* is_pointer */) { // Implementation for non-pointer types // Process value directly } template void process(T value) { process_impl(value, cslt::BoolConstant::value>{}); } Detection Idiom _______________ .. code-block:: cpp #include "utilities.hpp" // Detect if type has a nested ::value_type template struct HasValueType : cslt::FalseType { }; template struct HasValueType> : cslt::TrueType { }; // Usage static_assert(HasValueType>::value, ""); static_assert(!HasValueType::value, ""); Comparison with Standard Library ================================= This implementation closely follows the C++ standard library: ============================================== ==================================== csalt++ Component Standard Library Equivalent ============================================== ==================================== ``cslt::RemoveRef`` ``std::remove_reference`` ``cslt::IsLValueRef`` ``std::is_lvalue_reference`` ``cslt::IsSame`` ``std::is_same`` ``cslt::IsArray`` ``std::is_array`` ``cslt::IsConvertible`` ``std::is_convertible`` ``cslt::IsConstructible`` ``std::is_constructible`` ``cslt::IsAssignable`` ``std::is_assignable`` ``cslt::EnableIf`` ``std::enable_if`` ``cslt::move()`` ``std::move()`` ``cslt::forward()`` ``std::forward()`` ``cslt::swap()`` ``std::swap()`` ``cslt::declval()`` ``std::declval()`` ============================================== ==================================== Key Differences _______________ * Simplified implementations focused on core functionality * Missing some advanced traits (``RemoveConst``, ``RemoveCV``, ``Decay``, etc.) * No C++17 ``_v`` helper variables (e.g., ``is_same_v``) * Control block infrastructure is part of ``utilities.hpp`` rather than separate Performance Characteristics =========================== Compile-Time Overhead _____________________ All type traits and metaprogramming utilities are evaluated at compile-time: * **Type traits**: O(1) instantiation depth, minimal compile-time cost * **SFINAE checks**: May increase compile times for complex overload sets * **Perfect forwarding**: No runtime overhead, generates optimal code Runtime Overhead ________________ * **move()**, **forward()**, **swap()**: Zero runtime overhead (inline, constexpr) * All utilities resolve to optimal assembly - equivalent to hand-written code * **declval()**: Never actually called (only used in unevaluated contexts) Future Enhancements =================== Potential additions for future versions: * Additional type manipulation traits (``RemoveConst``, ``RemoveCV``, ``AddConst``, ``Decay``) * C++17 features (inline variables: ``is_same_v``, ``enable_if_t``) * C++20 features (concepts-based versions) * Additional detection idiom helpers * More comprehensive standard library trait coverage