based

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

commit131c6b5b0cf82b745d34986c31e8bf6cd519e685
parent11bb8457b521c7a424c157031193d7ad539fb75b
authorDimitrije Dobrota <mail@dimitrijedobrota.com>
dateMon, 24 Mar 2025 12:50:54 +0100

Elementary type_traits

Diffstat:
Mexample/CMakeLists.txt|+
Aexample/type_traits.cpp|+++++++++++++++++++++++++++++++++++++++++++++++++++++++
Ainclude/based/type_traits.hpp|+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

3 files changed, 154 insertions(+), 0 deletions(-)


diff --git a/example/CMakeLists.txt b/example/CMakeLists.txt

@@ -23,5 +23,6 @@ endfunction()

add_example(instrumentation)
add_example(algorithm)
add_example(list)
add_example(type_traits)
add_folders(Example)

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

@@ -0,0 +1,55 @@

#include "based/type_traits.hpp"
struct irregular
{
irregular() = default;
irregular(const irregular&) = delete;
irregular(irregular&&) = delete;
irregular& operator=(const irregular&) = delete;
irregular& operator=(irregular&&) = delete;
~irregular() = default;
};
template<typename T>
struct identity
{
using input_types = std::tuple<T>;
using output_type = T;
output_type operator()(T val) { return val; }
};
struct identity_wrong_input_tuple
{
using input_types = int; // should be a tuple
using output_type = int;
output_type operator()(int val) { return val; }
};
struct identity_wrong_input_tuple_irregular
{
using input_types = std::tuple<irregular>; // should be a regular tuple
using output_type = int;
output_type operator()(irregular /* val */) { return 1; }
};
int main()
{
static_assert(std::same_as<based::domain_t<identity<int>>, std::tuple<int>>);
static_assert(based::arity_v<identity<int>> == 1);
static_assert(based::Procedure<identity<int>>);
static_assert(based::Procedure<identity<irregular>>);
static_assert(!based::Procedure<identity_wrong_input_tuple>);
static_assert(based::RegularProcedure<identity<int>>);
static_assert(!based::RegularProcedure<identity<irregular>>);
static_assert(!based::RegularProcedure<identity_wrong_input_tuple_irregular>);
}

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

@@ -0,0 +1,98 @@

#pragma once
#include <tuple>
#include <type_traits>
namespace based
{
template<typename T>
concept Regular = std::regular<T>;
template<typename>
struct is_tuple : std::false_type
{
};
template<typename... T>
struct is_tuple<std::tuple<T...>> : std::true_type
{
};
template<typename T>
inline constexpr bool is_tuple_v = is_tuple<T>::value;
template<class>
struct is_regular_tuple : std::false_type
{
};
template<template<class...> class Tuple, class... Types>
requires(Regular<Types> && ...)
struct is_regular_tuple<Tuple<Types...>> : std::true_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<typename P>
struct domain
{
using type = std::remove_reference_t<P>::input_types;
};
template<typename T>
using domain_t = typename domain<T>::type;
template<typename P>
struct codomain
{
using type = std::remove_reference_t<P>::output_type;
};
template<typename T>
using codomain_t = typename codomain<T>::type;
template<typename P>
concept Procedure = requires {
typename domain_t<P>;
typename codomain_t<P>;
requires(is_tuple_v<domain_t<P>>);
};
template<Procedure P>
struct arity
{
static constexpr auto value = std::tuple_size<domain_t<P>>::value;
};
template<Procedure P>
inline constexpr auto arity_v = arity<P>::value;
template<Procedure P, std::size_t Idx>
requires requires { Idx < arity_v<P>; }
struct domain_elem
{
using type = std::tuple_element_t<Idx, domain_t<P>>;
};
template<Procedure P, std::size_t Idx>
using domain_elem_t = typename domain_elem<P, Idx>::type;
template<typename P>
concept RegularProcedure = requires {
requires(Procedure<P>);
requires(RegularTuple<domain_t<P>>);
requires(Regular<codomain_t<P>>);
};
/*
template<typename P>
concept FunctionalProcedure = requires { requires(RegularProcedure<P>); };
*/
} // namespace based