ccutl  0.3.2
a C++ utilities library focused on flexibility and expressibility
Classes | Macros | Typedefs | Functions | Variables

Classes

struct  ctl::type_pack< Ts >
 
struct  ctl::value_pack< values >
 

Macros

#define CTL_EXISTS_CONCEPT(name, template_params_tuple, template_args_tuple)
 
#define CTL_TYPEOF_CONCEPT(name, template_params_tuple, template_args_tuple)
 

Typedefs

template<class T >
using ctl::rmcv = std::remove_cv_t< T >
 
template<class T >
using ctl::rmref = std::remove_reference_t< T >
 
template<class T >
using ctl::rmcvref = std::remove_cvref_t< T >
 
template<std::size_t idx, class... Ts>
using ctl::targ = detail::targ::type< idx, Ts... >
 

Functions

template<class T >
constexpr T && ctl::fwd (rmref< T > &t) noexcept
 
template<class T >
constexpr T && ctl::fwd (rmref< T > &&t) noexcept
 
template<std::size_t idx, class... Ts>
requires constexpr detail::arg::valid_indexable_pack< idx, Ts... > auto && ctl::arg (Ts &&... args) noexcept
 
template<std::input_iterator I, std::sentinel_for< I > S, class T , class Proj = std::identity>
requires constexpr std::indirect_binary_predicate< std::ranges::equal_to, std::projected< I, Proj >, T const * > bool ctl::found (I first, S last, T const &value, Proj proj={})
 
template<std::ranges::input_range R, class T , class Proj = std::identity>
requires constexpr std::indirect_binary_predicate< std::ranges::equal_to, std::projected< std::ranges::iterator_t< R >, Proj >, T const * > bool ctl::found (R &&r, T const &value, Proj proj={})
 
template<class T >
constexpr rmref< T > && ctl::mv (T &&t) noexcept
 
template<std::input_iterator I, std::sentinel_for< I > S, class Proj = std::identity, std::indirect_unary_predicate< std::projected< I, Proj >> Pred>
constexpr bool ctl::found_if (I first, S last, Pred pred={}, Proj proj={})
 
template<std::ranges::input_range R, class Proj = std::identity, std::indirect_unary_predicate< std::projected< std::ranges::iterator_t< R >, Proj >> Pred>
constexpr bool ctl::found_if (R &&r, Pred pred={}, Proj proj={})
 
template<detail::streq::stringlike... Strings>
 ctl::requires (sizeof...(Strings) > 1) inline const expr bool streq(Strings &&... strings) noexcept
 
template<std::integral L, std::integral R>
constexpr std::strong_ordering ctl::icmp (L l, R r) noexcept
 

Variables

template<template< class... > class Template, class... Args>
concept ctl::exists = detail::exists::impl<Template, Args...>
 
template<detail::lowest::arithmetic Arithmetic>
requires constexpr detail::lowest::has_numeric_limits_lowest< Arithmetic > Arithmetic ctl::lowest = std::numeric_limits<Arithmetic>::lowest()
 
template<detail::highest::arithmetic Arithmetic>
requires constexpr detail::highest::has_numeric_limits_max< Arithmetic > Arithmetic ctl::highest = std::numeric_limits<Arithmetic>::max()
 
template<class T , template< class... > class Template>
concept ctl::typeof = detail::typeof ::impl<T, Template>
 
template<class... Ts>
concept ctl::same = sizeof...(Ts) > 0 and detail::same::impl<0
 
template<class... Ts>
concept ctl::different = !same<Ts...>
 

Detailed Description

Macro Definition Documentation

◆ CTL_EXISTS_CONCEPT

#define CTL_EXISTS_CONCEPT (   name,
  template_params_tuple,
  template_args_tuple 
)
Value:
template < \
template <PPUTL_TUPLE_ARGS(template_params_tuple)> class Template_, \
PPUTL_TUPLE_ARGS(template_params_tuple)> \
concept name = requires { \
typename Template_<PPUTL_TUPLE_ARGS(template_args_tuple)>; \
}

creates a concept for specialization validity. different template parameter layouts require different SFINAE setups; use this macro to create a concept for a given parameter layout.

see ccutl.exists for an example using a (class...) paramter layout.

Parameters
name- final name of the concept
template_params_tuple- tupled template parameter types and names
template_args_tuple- tupled template argument invocation text
Note
template parameter names cannot be Template_
#include <ctl/different.h>
#include <ctl/same.h>
#include <ctl/exists_concept.h>
// create the concept 'exists'
CTL_EXISTS_CONCEPT(exists, (class... Ts), (Ts...));
// may only be specialized with templates that allow an int- type<int>
template <template<class...> class IntableTemplate>
requires exists<IntableTemplate, int>
struct example;
template <ctl::same<int>>
struct good;
template <ctl::different<int>>
struct bad;
constexpr bool ex0 = exists<good, int>; // true
constexpr bool ex1 = exists<bad, int>; // false

◆ CTL_TYPEOF_CONCEPT

#define CTL_TYPEOF_CONCEPT (   name,
  template_params_tuple,
  template_args_tuple 
)
Value:
namespace detail { \
namespace PPUTL_CAT(name, _concept_) { \
\
template <template <PPUTL_TUPLE_ARGS(template_params_tuple)> class, class> \
struct test { \
static constexpr bool result = false; \
}; \
\
template < \
template <PPUTL_TUPLE_ARGS(template_params_tuple)> class Template_, \
PPUTL_TUPLE_ARGS(template_params_tuple)> \
struct test<Template_, Template_<PPUTL_TUPLE_ARGS(template_args_tuple)>> { \
static constexpr bool result = true; \
}; \
\
} /* namespace PPUTL_CAT(name, _concept_) */ \
} /* namespace detail */ \
\
template < \
class T_, \
template <PPUTL_TUPLE_ARGS(template_params_tuple)> class Template_> \
concept name = \
detail::PPUTL_CAT(name, _concept_)::test<Template_, T_>::result

creates a template spececialization detection concept. different template parameter layouts require different SFINAE setups; use this macro to create a concept for a given parameter layout.

see ccutl.typeof for an example using a (class...) paramter layout.

Parameters
name- final name of the concept
template_params_tuple- tupled template parameter types and names
template_args_tuple- tupled template argument invocation text
Note
template parameter names cannot be Template_ or T_
#include <vector>
#include <tuple>
#include <array>
#include <ctl/typeof_concept.h>
using std::vector;
using std::array;
using std::tuple;
// template<class T, template<class... Ts> class Template>
// concept type_typeof = {sfinae};
CTL_TYPEOF_CONCEPT(type_typeof, (class... Ts), (Ts...));
constexpr bool ex0 = type_typeof<vector<int>, vector>; // true
constexpr bool ex1 = type_typeof<vector<int>, tuple>; // false
// template<class T, template<class T, std::size_t sz> class Template>
// concept type_size_typeof = {sfinae};
CTL_TYPEOF_CONCEPT(type_size_typeof, (class T, std::size_t sz), (T, sz));
constexpr bool ex2 = type_size_typeof<array<int, 3>, array>; // true
constexpr bool ex3 = type_size_typeof<tuple<int>, array>; // false

Typedef Documentation

◆ rmcv

template<class T >
using ctl::rmcv = typedef std::remove_cv_t<T>

shorthand for std::remove_cv_t

◆ rmcvref

template<class T >
using ctl::rmcvref = typedef std::remove_cvref_t<T>

shorthand for std::remove_cvref_t

◆ rmref

template<class T >
using ctl::rmref = typedef std::remove_reference_t<T>

shorthand for std::remove_reference_t

◆ targ

template<std::size_t idx, class... Ts>
using ctl::targ = typedef detail::targ::type<idx, Ts...>

represents the type template argument at index idx

#include "ctl/targ.h"
using x0 = ctl::targ<0, int, float, double>; // int
using x1 = ctl::targ<1, int, float, double>; // float
using x2 = ctl::targ<2, int, float, double>; // double

Function Documentation

◆ arg()

template<std::size_t idx, class... Ts>
requires constexpr detail::arg::valid_indexable_pack<idx, Ts...> auto&& ctl::arg ( Ts &&...  args)
inlineconstexprnoexcept

returns the passed arg by index, preserving reference qualifier

#include "ctl/arg.h"
char c = 'c';
auto &&x0 = ctl::arg<0>('a', "b", c); // (char) 'a'
auto &&x1 = ctl::arg<1>('a', "b", c); // (char const*) "b"
auto &&x2 = ctl::arg<2>('a', "b", c); // (char &) c

◆ found() [1/2]

template<std::input_iterator I, std::sentinel_for< I > S, class T , class Proj = std::identity>
requires constexpr std::indirect_binary_predicate<std::ranges::equal_to, std::projected<I, Proj>, T const*> bool ctl::found ( first,
last,
T const &  value,
Proj  proj = {} 
)
inlineconstexpr

checks if a value is found within a range mirrors std::ranges::find; returns boolean

◆ found() [2/2]

template<std::ranges::input_range R, class T , class Proj = std::identity>
requires constexpr std::indirect_binary_predicate< std::ranges::equal_to, std::projected<std::ranges::iterator_t<R>, Proj>, T const*> bool ctl::found ( R &&  r,
T const &  value,
Proj  proj = {} 
)
inlineconstexpr

checks if a value is found within a range mirrors std::ranges::find; returns boolean

◆ found_if() [1/2]

template<std::input_iterator I, std::sentinel_for< I > S, class Proj = std::identity, std::indirect_unary_predicate< std::projected< I, Proj >> Pred>
constexpr bool ctl::found_if ( first,
last,
Pred  pred = {},
Proj  proj = {} 
)
inlineconstexpr

checks if a predicate is true for any value in a range mirrors std::ranges::find_if

◆ found_if() [2/2]

template<std::ranges::input_range R, class Proj = std::identity, std::indirect_unary_predicate< std::projected< std::ranges::iterator_t< R >, Proj >> Pred>
constexpr bool ctl::found_if ( R &&  r,
Pred  pred = {},
Proj  proj = {} 
)
inlineconstexpr

checks if a predicate is true for any value in a range mirrors std::ranges::find_if

◆ fwd() [1/2]

template<class T >
constexpr T&& ctl::fwd ( rmref< T > &&  t)
constexprnoexcept

perfect forwarder for rvalues

◆ fwd() [2/2]

template<class T >
constexpr T&& ctl::fwd ( rmref< T > &  t)
constexprnoexcept

perfect forwarder for lvalues

◆ icmp()

template<std::integral L, std::integral R>
constexpr std::strong_ordering ctl::icmp ( l,
r 
)
inlineconstexprnoexcept

performs a three-way comparison of two integrals of any sign

Parameters
l- left-hand side
r- right-hand side
Returns
result of strongly ordered three-way comparison
#include "ctl/icmp.h"
ctl::icmp(0, 0); // strong_ordering::equal
ctl::icmp(0, 0u); // strong_ordering::equal
ctl::icmp(0u, 0); // strong_ordering::equal
ctl::icmp(0u, 0u); // strong_ordering::equal
ctl::icmp(0, 1); // strong_ordering::less
ctl::icmp(1, 0u); // strong_ordering::greater
ctl::icmp(0u, 1); // strong_ordering::less
ctl::icmp(0, 1u); // strong_ordering::less
ctl::icmp(1u, 0); // strong_ordering::greater
ctl::icmp(1u, 1u); // strong_ordering::equal
ctl::icmp(-1, -1); // strong_ordering::equal
ctl::icmp(-1, 0u); // strong_ordering::less
ctl::icmp(0u, -1); // strong_ordering::greater
ctl::icmp(-1, 1); // strong_ordering::less
ctl::icmp(1, -1); // strong_ordering::greater

◆ mv()

template<class T >
constexpr rmref<T>&& ctl::mv ( T &&  t)
constexprnoexcept

move an rvalue

◆ requires()

template<detail::streq::stringlike... Strings>
ctl::requires ( sizeof...  Strings,
 
) const &&
noexcept

equality comparison of stringlike objects

Variable Documentation

◆ different

template<class... Ts>
concept ctl::different = !same<Ts...>

describes a set of types with at least one variation

#include "ctl/different.h"
auto x0 = ctl::different<int, int, int>; // false
auto x1 = ctl::different<int, int &, int>; // true

◆ exists

template<template< class... > class Template, class... Args>
concept ctl::exists = detail::exists::impl<Template, Args...>

defines templates that are specializable by Ts...

Note
may only be used with template structs, classes, and unions
#include "ctl/exists.h"
#include "ctl/same.h"
using std::tuple;
template <ctl::same<int> T>
struct foo {};
auto x0 = ctl::exists<foo, int>; // true
auto x1 = ctl::exists<foo, int, int>; // false
auto x2 = ctl::exists<foo, long>; // false

◆ highest

template<detail::highest::arithmetic Arithmetic>
requires constexpr detail::highest::has_numeric_limits_max<Arithmetic> Arithmetic ctl::highest = std::numeric_limits<Arithmetic>::max()
inlineconstexpr

represents the highest number possible for a given arithmetic type

Note
mirrors std::numeric_limits<T>::max()
#include "ctl/highest.h"
auto x0 = ctl::highest<int8_t>; // 127
auto x1 = ctl::highest<int16_t>; // 32767
auto x2 = ctl::highest<float>; // 3.40283e+38

◆ lowest

template<detail::lowest::arithmetic Arithmetic>
requires constexpr detail::lowest::has_numeric_limits_lowest<Arithmetic> Arithmetic ctl::lowest = std::numeric_limits<Arithmetic>::lowest()
inlineconstexpr

represents the lowest number possible for a given arithmetic type

Note
mirrors std::numeric_limits<T>::lowest()
#include "ctl/lowest.h"
auto x0 = ctl::lowest<int8_t>; // -128
auto x1 = ctl::lowest<int16_t>; // -32768
auto x2 = ctl::lowest<float>; // -3.40283e+38

◆ same

template<class... Ts>
concept ctl::same = sizeof...(Ts) > 0 and detail::same::impl<0

describes a set of types with no variation

#include "ctl/same.h"
static_assert( same<int, int, int>);
static_assert(!same<int, int &, int>);

◆ typeof

template<class T , template< class... > class Template>
concept ctl::typeof = detail::typeof ::impl<T, Template>

Detects template specializations for type-parameter templates (<class...>)

#include <tuple>
#include "ctl/typeof.h"
using std::tuple;
auto x0 = ctl::typeof<tuple<int, int>, tuple>; // true
auto x1 = ctl::typeof<tuple<int, int>, pair>; // false

CTL_TYPEOF_CONCEPT
#define CTL_TYPEOF_CONCEPT(name, template_params_tuple, template_args_tuple)
Definition: ccutl.h:1130
ctl::detail::streq::requires
requires(sizeof...(Rest) > 1) inline const expr bool impl(First &&first
compare more than two stringlike objects
PPUTL_TUPLE_ARGS
#define PPUTL_TUPLE_ARGS(tup)
Definition: ccutl.h:82
CTL_EXISTS_CONCEPT
#define CTL_EXISTS_CONCEPT(name, template_params_tuple, template_args_tuple)
Definition: ccutl.h:693
ctl::exists
concept exists
Definition: ccutl.h:822
PPUTL_CAT
#define PPUTL_CAT(...)
Definition: ccutl.h:369
ctl::requires
requires(sizeof...(Strings) > 1) inline const expr bool streq(Strings &&... strings) noexcept
Definition: ccutl.h:1877
ctl::icmp
constexpr std::strong_ordering icmp(L l, R r) noexcept
Definition: ccutl.h:1989