Tools

Functional

#include<hysj/tools/functional.hpp>

unspecified apply
unspecified assign
unspecified holds_alternative
Lifts of std::apply, assignment and std::holds_alternative.

unspecified decay_copy
Implements P0849.

unspecified any_of
unspecified none_of
any_of(x...) \(\rightarrow f\) where:
\(f(y) = \exists y \in \{ x\dots \}\)
none_of(x...) \(\rightarrow f\) where:
\(f(y) = \nexists y \in \{ x\dots \}\)

unspecified unwrap
unwrap(x) unwraps x if it’s a std::reference_wrapper, else forwards.

unspecified overload
Functional overload-set.

unspecified visitor
g = visitor(f...) creates a visitor of the overload set f…, which exposes:
operator()(auto&&... v)
Calls std::visit with variants v...

unspecified always
always(x) \(\rightarrow f\) where:
\(f(y \ldots) = x\)

Is awaitable, immediately resuming with y.

template<int... i>
unspecified bind
bind<i...>(f, x...) \(\rightarrow g\) where:
\(g(y...) = f(z...)\)
\(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}\)
\(J^x = \{ h(k) \mid \forall k \in |X| \}\)
\(h(k) = \begin{cases} i_k \geq 0 \rightarrow i_k \\ i_k < 0 \rightarrow |X| + |Y| - i_k \end{cases}\)
\(J^y = |X| \cup |Y| \setminus J^x\).

Example

\(f(x) = 1 - x\), \(g(x) = x - 1\), and \(h() = 1 - 1\):

auto f = bind<0>(std::minus<>{},1)
auto g = bind<-1>(std::minus<>{},1)
auto h = bind<0,-1>(std::minus<>{},1,1);

template<integer... i>
unspecified combine
combine<i...>(f, g) \(\rightarrow h\) where:
\(h(x...) = f(y...)\)
\(y_j = \begin{cases} j \in J^g \rightarrow g(x_j) \\ j \notin J^g \rightarrow x_j \end{cases}\)
\(J^x = \{ h(k) \mid \forall k \in |X| \}\)
\(h(k) = \begin{cases} i_k \geq 0 \rightarrow i_k \\ i_k < 0 \rightarrow |X| - i_k \end{cases}\)

Example

\(f_0(x,y) = h(x) + y\), \(f_1(x,y) = x + h(y)\), \(h(x) = 1\):

auto h = always(1);
auto f_0 = combine<0>(std::plus<>{},h);
auto f_1 = combine<-1>(std::plus<>{},h);

template<integer N>
unspecified compose
compose<N>(f, g...) \(\rightarrow h\) where:
\(h(x\ldots) = f(y\ldots, (g_0 \circ \ldots \circ g_n)(z\ldots),w\ldots)\)
\(Z = \begin{cases} N = 0 \rightarrow |X| \\ N < 0 \rightarrow |X| \setminus ||X| - N| \\ N > 0 \rightarrow |N| \end{cases}\)
\(Y = \begin{cases} N \geq 0 \rightarrow \emptyset \\ N < 0 \rightarrow |X| \setminus Z \end{cases}\)
\(W = \begin{cases} N \leq 0 \rightarrow \emptyset \\ N > 0 \rightarrow |X| \setminus Z \end{cases}\)

Example

\(f_0(x,y,z) = (g \circ h)(x,y,z)\), \(f_1(x,y,z) = g(h(x),y,z)\), and \(f_2(x,y,z) = g(x,(h \circ h)(y,z))\):

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);

template<integer... i>
unspecified interpose
interpose<i...>(f, g...) \(\rightarrow h\) where:
\(h(x\ldots) = h(y\ldots)\)
\(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}\)
\(J^g = \{ h(k) \mid \forall k \in |X| \}\)
\(h(k) = \begin{cases} i_k \geq 0 \rightarrow i_k \\ i_k < 0 \rightarrow |X| - i_k \end{cases}\)

Example

\(f_0(x,y,z) = g(h_0(x),y,z)\), \(f_1(x,y,z) = g(h_0(x),y,h_1(z))\):

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

#include<hysj/tools/preprocessor.hpp>

The preprocessor module defines helper-macros for working with sequences up to 24 elements long.

HYSJ_PRODUCT(sequences)
Compute the cartesian product of a sequence of sequences.

Example

Defining the sequence S = ((0, 2)(1, 2)):

#define U0 (0)(1)
#define U1 (2)
#define S HYSJ_PRODUCT((U0)(U1))

HYSJ_MAP_LAMBDA(sequence)
Maps sequence with HYSJ_LAMBDA, which the user defines before invokation (and preferably undefines after invocation).

Example

Declaring two ints, i0 = 0 and i1 = 1:

#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);

HYSJ_SPLAT(i, sequence)
Splats the ith element of each value in sequence into a list.

Example

Splating the last value of each element in the sequence (0, 1)(0, 1) into an array.

#define S (0,1)(0,1)
std::array s{ HYSJ_SPLAT(1,S) };
static_assert(s == std::array{1,1});

HYSJ_PROJECT(i, sequence)
Creates a new sequence consisting of the ith element of each value in sequence into a list.

Example

Projecting the sequence (0, 1)(0, 1) into a new sequence (0)(0):

#define S (0,1)(0,1)
#define U HYSJ_PROJECT(0,S)

HYSJ_QUALIFIERS
List of member-ref-qualifiers and associated forwarding function.

Example

Spitting out member-ref qualified overloads of a function call operator:

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

#include<hysj/tools/priority_tag.hpp>

template<std::size_t N>
struct 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.

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

#include<hysj/tools/reflection.hpp>

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.

struct enumerator_mirror
unspecified value
unspecified name

struct reflection::enum_mirror
unspecified name
auto enumerators(enum_mirror)
Returns a tuple of the reflected members.

HYSJ_MIRROR_ENUM(E, ...)

Sets up a mirror for an enumerator.

Example

enum myenum{a,b};
HYSJ_MIRROR_ENUM(myenum,a,b);
auto [a_mirror,b_mirror] = enumerators(reflect<myenum>());
static_assert(a_mirror.value == a);
static_assert(b_mirror.value == b);

struct reflection::member_mirror
unspecified pointer
unspecified name

struct reflection::struct_mirror
unspecified name
auto members(struct_mirror)
Returns a tuple of the reflected members.

HYSJ_MIRROR_STRUCT(E, ...)

Sets up a mirror for a struct.

Example

struct mystruct{
  int a,b;
  friend HYSJ_MIRROR_STRUCT(mystruct,a,b);
};
auto [a_mirror,b_mirror] = members(reflect<mystruct>());
static_assert(a_mirror.pointer == &mystruct::a);
static_assert(b_mirror.pointer == &mystruct::b);

template<class T>
auto reflection::reflect()
Get the mirror of T.

Tag Invoke

#include<hysj/tools/tag_invoke.hpp>

Machinery for setting up hooks (or CPOs). Stolen from Niebler’s gist.

Tuple

#include<hysj/tools/tuple.hpp>

Helper functions for working with tuples, arrays, and spans.

Types

#include<hysj/tools/types.hpp>

struct nothing
Regular void.

using real = double
using natural = uint64_t
using integer = int64_t
using ptrdiff = std::ptrdiff_t
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.

template<natural N>
using natural_t
template<ptrdiff N>
using ptrdiff_t
template<natural N>
unspecified natural_c
template<ptrdiff N>
unspecified ptrdiff_c
template<char...>
constexpr auto operator""_N()
template<char...>
constexpr auto operator""_P()
Integral-constant machinery for natural and ptrdiff.

Type Traits

#include<hysj/tools/type_traits.hpp>

template<class T, class U>
concept not_same_as
Inverts std::same_as.

template<class T>
using unref_t
template<class T>
using uncvref_t
Removes references (and const) and unpacks std::reference_wrapper.

template<class T, bool C>
using add_const_if
\(\textit{add_const_if}(T,C) = \begin{cases} C = \top \rightarrow \textit{const}\;T \\ C = \bot \rightarrow T \end{cases}\)

template<class T>
using type_t
template<class T>
unspecified type_c
Shorthands for std::identity_type.

template<auto i>
using constant_t
template<auto i>
unspecified constant_c
Shorthands for std::integral_constant.

template<class T>
concept is_constant
template<class T, class U>
concept is_constant_of
template<class X, class Y>
consteval auto is_same_constant(X, Y)
Machinery for comparing integral-constants.

template<class T>
constexpr bool is_scoped_enum_v
Checks if T is a scoped enum.

template<class T>
bool is_std_vector
template<class T>
bool is_std_reference_wrapper
template<class T>
bool is_std_array
template<class T>
bool is_std_span
Checks if T is a std-type.

template<auto pointer>
using member_type = unspecified
\(\textit{member_type}(T \textit{X::*} \textit{pointer}) = T\)

Utility

#include<hysj/tools/utility.hpp>

template<typename E>
auto to_underlying(E e)
template<typename E, E e>
auto to_underlying(std::integral_constant<E, e>)
Converts an enum to its underlying type.