Tools ===== .. cpp:namespace:: hysj Functional ---------- :cpp:include:`#include` .. cpp:var:: unspecified apply unspecified assign unspecified holds_alternative | Lifts of :cppref:`std::apply `, assignment and :cppref:`std::holds_alternative `. | .. cpp:var:: unspecified decay_copy | Implements `P0849 `_. | .. cpp:var:: unspecified any_of unspecified none_of | :cpp:expr:`any_of(x...)` :math:`\rightarrow f` where: | :math:`f(y) = \exists y \in \{ x\dots \}` | :cpp:expr:`none_of(x...)` :math:`\rightarrow f` where: | :math:`f(y) = \nexists y \in \{ x\dots \}` | .. cpp:var:: unspecified unwrap | :cpp:expr:`unwrap(x)` unwraps :cpp:expr:`x` if it's a :cppref:`std::reference_wrapper `, else forwards. | .. cpp:var:: unspecified overload | Functional overload-set. | .. cpp:var:: unspecified visitor | :cpp:expr:`g = visitor(f...)` creates a visitor of the overload set `f...`, which exposes: .. cpp:function:: operator()(auto &&... v) | Calls :cppref:`std::visit ` with variants :cpp:expr:`v...` | .. cpp:var:: unspecified always | :cpp:expr:`always(x)` :math:`\rightarrow f` where: | :math:`f(y \ldots) = x` | | Is awaitable, immediately resuming with :cpp:expr:`y`. | .. cpp:var:: template unspecified bind | :cpp:expr:`bind(f,x...)` :math:`\rightarrow g` where: | :math:`g(y...) = f(z...)` | :math:`z_j = \begin{cases} j = j^x_k \in J^X \rightarrow x_{k} \\ j = j^y_k \in J^Y \rightarrow y_k \end{cases}` | :math:`J^x = \{ h(k) \mid \forall k \in |X| \}` | :math:`h(k) = \begin{cases} i_k \geq 0 \rightarrow i_k \\ i_k < 0 \rightarrow |X| + |Y| - i_k \end{cases}` | :math:`J^y = |X| \cup |Y| \setminus J^x`. *Example* :math:`f(x) = 1 - x`, :math:`g(x) = x - 1`, and :math:`h() = 1 - 1`: .. code-block:: cpp auto f = bind<0>(std::minus<>{},1) auto g = bind<-1>(std::minus<>{},1) auto h = bind<0,-1>(std::minus<>{},1,1); | .. cpp:var:: template unspecified combine | :cpp:expr:`combine(f,g)` :math:`\rightarrow h` where: | :math:`h(x...) = f(y...)` | :math:`y_j = \begin{cases} j \in J^g \rightarrow g(x_j) \\ j \notin J^g \rightarrow x_j \end{cases}` | :math:`J^x = \{ h(k) \mid \forall k \in |X| \}` | :math:`h(k) = \begin{cases} i_k \geq 0 \rightarrow i_k \\ i_k < 0 \rightarrow |X| - i_k \end{cases}` *Example* :math:`f_0(x,y) = h(x) + y`, :math:`f_1(x,y) = x + h(y)`, :math:`h(x) = 1`: .. code-block:: cpp auto h = always(1); auto f_0 = combine<0>(std::plus<>{},h); auto f_1 = combine<-1>(std::plus<>{},h); | .. cpp:var:: template unspecified compose | :cpp:expr:`compose(f,g...)` :math:`\rightarrow h` where: | :math:`h(x\ldots) = f(y\ldots, (g_0 \circ \ldots \circ g_n)(z\ldots),w\ldots)` | :math:`Z = \begin{cases} N = 0 \rightarrow |X| \\ N < 0 \rightarrow |X| \setminus ||X| - N| \\ N > 0 \rightarrow |N| \end{cases}` | :math:`Y = \begin{cases} N \geq 0 \rightarrow \emptyset \\ N < 0 \rightarrow |X| \setminus Z \end{cases}` | :math:`W = \begin{cases} N \leq 0 \rightarrow \emptyset \\ N > 0 \rightarrow |X| \setminus Z \end{cases}` *Example* :math:`f_0(x,y,z) = (g \circ h)(x,y,z)`, :math:`f_1(x,y,z) = g(h(x),y,z)`, and :math:`f_2(x,y,z) = g(x,(h \circ h)(y,z))`: .. code-block:: cpp auto g = [](auto...){}; auto h = [](auto...){}; auto f_0 = compose<0>(g,h) auto f_1 = compose<1>(g,h); auto f_2 = compose<-2>(g,h,h); | .. cpp:var:: template unspecified interpose | :cpp:expr:`interpose(f,g...)` :math:`\rightarrow h` where: | :math:`h(x\ldots) = h(y\ldots)` | :math:`y_j = \begin{cases} j = j^g_k\in J^g \rightarrow g_k(x_j) \\ j \notin J^g \rightarrow x_j \end{cases}` | :math:`J^g = \{ h(k) \mid \forall k \in |X| \}` | :math:`h(k) = \begin{cases} i_k \geq 0 \rightarrow i_k \\ i_k < 0 \rightarrow |X| - i_k \end{cases}` *Example* :math:`f_0(x,y,z) = g(h_0(x),y,z)`, :math:`f_1(x,y,z) = g(h_0(x),y,h_1(z))`: .. code-block:: cpp auto g = [](auto...){}; auto h_0= [](auto...){}; auto h_1 = [](auto...){}; auto f_0 = interpose<0>(g,h_0) auto f_1 = interpose<0,-1>(g,h_0,h_1); | Preprocessor ------------ :cpp:include:`#include` The preprocessor module defines helper-macros for working with sequences up to 24 elements long. .. c:macro:: HYSJ_PRODUCT(sequences) | Compute the cartesian product of a sequence of sequences. *Example* Defining the sequence :cpp:expr:`S = ((0,2)(1,2))`: .. code-block:: cpp #define U0 (0)(1) #define U1 (2) #define S HYSJ_PRODUCT((U0)(U1)) | .. c:macro:: HYSJ_MAP_LAMBDA(sequence) | Maps :cpp:expr:`sequence` with :c:macro:`HYSJ_LAMBDA`, which the user defines before invokation (and preferably undefines after invocation). *Example* Declaring two ints, :cpp:expr:`i0 = 0` and :cpp:expr:`i1 = 1`: .. code-block:: cpp #define S (0)(1) #define HYSJ_LAMBDA(v) int i##v = v; HYSJ_MAP_LAMBDA(S) #undef MYSJ_LAMBDA static_assert(i0 == 0 && i1 == 1); | .. c:macro:: HYSJ_SPLAT(i,sequence) | Splats the ith element of each value in :cpp:expr:`sequence` into a list. *Example* Splating the last value of each element in the sequence :cpp:expr:`(0,1)(0,1)` into an array. .. code-block:: cpp #define S (0,1)(0,1) std::array s{ HYSJ_SPLAT(1,S) }; static_assert(s == std::array{1,1}); | .. c:macro:: HYSJ_PROJECT(i,sequence) | Creates a new sequence consisting of the ith element of each value in :cpp:expr:`sequence` into a list. *Example* Projecting the sequence :cpp:expr:`(0,1)(0,1)` into a new sequence :cpp:expr:`(0)(0)`: .. code-block:: cpp #define S (0,1)(0,1) #define U HYSJ_PROJECT(0,S) | .. c:macro:: HYSJ_QUALIFIERS | List of member-ref-qualifiers and associated forwarding function. *Example* Spitting out member-ref qualified overloads of a function call operator: .. code-block:: cpp struct int_holder{ int x; static auto impl(auto&& h,auto &&f) arrow((fwd(f)(fwd(h).x))) #define HYSJ_LAMBDA(qualifier,function)\ auto operator()(auto && f) qualifier\ arrow((impl(function(*this), fwd(f)))) HYSJ_MAP_LAMBDA(HYSJ_QUALIFIERS) #undef HYSJ_LAMBDA }; Priority Tag ------------ :cpp:include:`#include` .. cpp:struct:: template priority_tag | Helper type for defining a prioritized list of default implementations for a hook. *Example* Setting up a hook that by default first tries to invoke a member-function, and if that fails tries to invoke a free function. .. code-block:: cpp inline constexpr struct hook_fn{ friend auto ordered_tag_invoke(hook_fn,priority_tag<1>,auto f) arrow((f.hook())) friend auto ordered_tag_invoke(hook_fn,priority_tag<0>,auto f) arrow((hook(f))) friend auto tag_invoke(hook_fn fn,auto f) arrow((ordered_tag_invoke(fn,priority_tag<1>{},f))) auto operator()(auto f)const arrow((tag_invoke(*this,f))) } hook{}; Reflection ---------- :cpp:include:`#include` Facilities for rudimentary compile-time reflection of enums and structs. Was orignally adapted from `describe `_. Provides two convenience macros to set up mirrors which encapsulate information about the type, as well as a list of mirrors for its members or enumerators. .. cpp:struct:: enumerator_mirror .. cpp:var:: unspecified value .. cpp:var:: unspecified name | .. cpp:struct:: reflection::enum_mirror .. cpp:var:: unspecified name .. cpp:function:: auto enumerators(enum_mirror) | Returns a tuple of the reflected members. | .. c:macro:: HYSJ_MIRROR_ENUM(E, ...) Sets up a mirror for an enumerator. *Example* .. code-block:: cpp enum myenum{a,b}; HYSJ_MIRROR_ENUM(myenum,a,b); auto [a_mirror,b_mirror] = enumerators(reflect()); static_assert(a_mirror.value == a); static_assert(b_mirror.value == b); | .. cpp:struct:: reflection::member_mirror .. cpp:var:: unspecified pointer .. cpp:var:: unspecified name | .. cpp:struct:: reflection::struct_mirror .. cpp:var:: unspecified name .. cpp:function:: auto members(struct_mirror) | Returns a tuple of the reflected members. | .. c:macro:: HYSJ_MIRROR_STRUCT(E, ...) Sets up a mirror for a struct. *Example* .. code-block:: cpp struct mystruct{ int a,b; friend HYSJ_MIRROR_STRUCT(mystruct,a,b); }; auto [a_mirror,b_mirror] = members(reflect()); static_assert(a_mirror.pointer == &mystruct::a); static_assert(b_mirror.pointer == &mystruct::b); | .. cpp:function:: template auto reflection::reflect() | Get the mirror of :cpp:type:`T`. | Tag Invoke ---------- :cpp:include:`#include` Machinery for setting up hooks (or CPOs). Stolen from `Niebler's gist `_. Tuple ----- :cpp:include:`#include` Helper functions for working with tuples, arrays, and spans. Types ----- :cpp:include:`#include` .. cpp:struct:: nothing | Regular void. | .. cpp:type:: real = double natural = uint64_t integer = int64_t ptrdiff = std::ptrdiff_t .. cpp:function:: real operator ""_r(long double) natural operator ""_n(unsigned long long int) integer operator ""_i(unsigned long long int) ptrdiff operator ""_p(unsigned long long int) | Aliases and string literals for basic types. | .. cpp:type:: template natural_t template ptrdiff_t .. cpp:var:: template unspecified natural_c template unspecified ptrdiff_c .. cpp:function:: template constexpr auto operator ""_N() template constexpr auto operator ""_P() | Integral-constant machinery for :cpp:type:`natural` and :cpp:type:`ptrdiff`. | Type Traits ----------- :cpp:include:`#include` .. cpp:concept:: template not_same_as | Inverts :cppref:`std::same_as `. | .. cpp:type:: template unref_t template uncvref_t | Removes references (and const) and unpacks :cppref:`std::reference_wrapper `. | .. cpp:type:: template add_const_if | :math:`\textit{add_const_if}(T,C) = \begin{cases} C = \top \rightarrow \textit{const}\;T \\ C = \bot \rightarrow T \end{cases}` | .. cpp:type:: template type_t .. cpp:var:: template unspecified type_c | Shorthands for :cppref:`std::identity_type `. | .. cpp:type:: template constant_t .. cpp:var:: template unspecified constant_c | Shorthands for :cppref:`std::integral_constant `. | .. cpp:concept:: template is_constant template is_constant_of .. cpp:function:: template consteval auto is_same_constant(X,Y) | Machinery for comparing integral-constants. | .. cpp:var:: template constexpr bool is_scoped_enum_v | Checks if :cpp:type:`T` is a scoped enum. | .. cpp:var:: template bool is_std_vector template bool is_std_reference_wrapper template bool is_std_array template bool is_std_span | Checks if :cpp:type:`T` is a std-type. | .. cpp:type:: template member_type = unspecified | :math:`\textit{member_type}(T \textit{X::*} \textit{pointer}) = T` | Utility ------- :cpp:include:`#include` .. cpp:function:: template auto to_underlying(E e) template auto to_underlying(std::integral_constant) | Converts an enum to its underlying type. |