based

Opinionated utility library
git clone git://git.dimitrijedobrota.com/based.git
Log | Files | Refs | README | HACKING | CONTRIBUTING | CODE_OF_CONDUCT | BUILDING |

commit40dceb5e125e80c527dd2f3c33eac6a2e0c36feb
parent7d46d516559e7bca2d59ae72ae66b04918ad9fd0
authorDimitrije Dobrota <mail@dimitrijedobrota.com>
dateTue, 25 Mar 2025 18:37:17 +0100

Add FunctionalProcedure and fixups

Diffstat:
Mexample/type_traits.cpp|+++++++++++++++++++++++++++++++++++--
Minclude/based/type_traits.hpp|+++++++++++++++++++++++++++++++++++++++++++++++++----

2 files changed, 84 insertions(+), 6 deletions(-)


diff --git a/example/type_traits.cpp b/example/type_traits.cpp

@@ -22,9 +22,21 @@ struct identity

template<typename T, typename U>
struct add
{
T operator()(T val1, U val2) { return val1 + val2; }
T operator()(const T& val1, const U& val2) { return val1 + val2; }
};
template<typename T>
struct mutate
{
T operator()(T* val) { return *val = 1; }
};
template<typename T, typename U>
T sub(T val1, U val2) // NOLINT
{
return val1 - val2;
}
int main()
{
using id = identity<double>;

@@ -40,12 +52,16 @@ int main()

static_assert(based::RegularProcedure<id>);
static_assert(!based::RegularProcedure<ii>);
static_assert(based::FunctionalProcedure<id>);
static_assert(!based::FunctionalProcedure<ii>);
using ad = add<double, double>;
using ai = add<irregular, irregular>;
using aid = add<irregular, double>;
using adi = add<double, irregular>;
static_assert(std::same_as<based::domain_t<ad>, std::tuple<double, double>>);
static_assert(std::same_as<based::domain_t<ad>,
std::tuple<const double&, const double&>>);
static_assert(std::same_as<based::codomain_t<ad>, double>);
static_assert(based::arity_v<ad> == 2);

@@ -59,9 +75,26 @@ int main()

static_assert(!based::RegularProcedure<aid>);
static_assert(!based::RegularProcedure<adi>);
static_assert(based::FunctionalProcedure<ad>);
static_assert(!based::FunctionalProcedure<ai>);
static_assert(!based::FunctionalProcedure<aid>);
static_assert(!based::FunctionalProcedure<adi>);
using md = mutate<double>;
static_assert(based::Procedure<md>);
static_assert(based::RegularProcedure<md>);
static_assert(!based::FunctionalProcedure<md>);
static_assert(based::RegularProcedure<decltype(sub<double, double>)>);
static const auto l1 = [](double a) { return a; };
static_assert(based::Procedure<decltype(l1)>);
static_assert(based::RegularProcedure<decltype(l1)>);
static_assert(based::FunctionalProcedure<decltype(l1)>);
static const auto l2 = [](irregular /* a */) { return 1; };
static_assert(based::Procedure<decltype(l2)>);
static_assert(!based::RegularProcedure<decltype(l2)>);
static_assert(!based::FunctionalProcedure<decltype(l2)>);
}

diff --git a/include/based/type_traits.hpp b/include/based/type_traits.hpp

@@ -9,6 +9,17 @@ namespace based

template<typename T>
concept Regular = std::regular<T>;
template<typename T>
concept Input =
std::same_as<T,
std::remove_volatile_t<
std::remove_reference_t<std::remove_pointer_t<T>>>>
|| (std::is_lvalue_reference_v<T>
&& std::is_const_v<std::remove_reference_t<T>>);
template<typename P, typename... Args>
concept Invokable = std::invocable<P, Args...>;
template<typename Fun>
concept FreeProcedure = std::is_function_v<Fun>;

@@ -29,17 +40,34 @@ struct is_regular_tuple : std::false_type

};
template<template<class...> class Tuple, class... Types>
requires(Regular<Types> && ...)
requires(Regular<std::remove_cvref_t<Types>> && ...)
struct is_regular_tuple<Tuple<Types...>> : std::true_type
{
};
template<class>
struct is_input_tuple : std::false_type
{
};
template<class T>
inline constexpr bool is_regular_tuple_v = is_regular_tuple<T>::value;
template<class T>
concept RegularTuple = is_regular_tuple_v<T>;
template<template<class...> class Tuple, class... Types>
requires(Input<Types> && ...)
struct is_input_tuple<Tuple<Types...>> : std::true_type
{
};
template<class T>
inline constexpr bool is_input_tuple_v = is_input_tuple<T>::value;
template<class T>
concept InputTuple = is_input_tuple_v<T>;
template<typename>
struct signature;

@@ -48,6 +76,9 @@ struct signature<Ret(Args...)>

{
using arg_type = std::tuple<Args...>;
using ret_type = Ret;
using const_value = std::false_type;
using volataile_value = std::false_type;
};
template<typename Ret, typename Obj, typename... Args>

@@ -55,6 +86,9 @@ struct signature<Ret (Obj::*)(Args...)>

{
using arg_type = std::tuple<Args...>;
using ret_type = Ret;
using const_value = std::false_type;
using volataile_value = std::false_type;
};
template<typename Ret, typename Obj, typename... Args>

@@ -62,6 +96,9 @@ struct signature<Ret (Obj::*)(Args...) const>

{
using arg_type = std::tuple<Args...>;
using ret_type = Ret;
using const_value = std::true_type;
using volataile_value = std::false_type;
};
template<typename Ret, typename Obj, typename... Args>

@@ -69,6 +106,9 @@ struct signature<Ret (Obj::*)(Args...) volatile>

{
using arg_type = std::tuple<Args...>;
using ret_type = Ret;
using const_value = std::false_type;
using volataile_value = std::true_type;
};
template<typename Ret, typename Obj, typename... Args>

@@ -76,6 +116,9 @@ struct signature<Ret (Obj::*)(Args...) const volatile>

{
using arg_type = std::tuple<Args...>;
using ret_type = Ret;
using const_value = std::true_type;
using volataile_value = std::true_type;
};
template<typename>

@@ -152,8 +195,10 @@ concept RegularProcedure = requires {

requires(Regular<codomain_t<P>>);
};
/*
template<typename P>
concept FunctionalProcedure = requires { requires(RegularProcedure<P>); };
*/
concept FunctionalProcedure = requires {
requires(RegularProcedure<P>);
requires(InputTuple<domain_t<P>>);
};
} // namespace based