based

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

commit 731a0b1a3f91f31037a48f5df9c5c9691a58728a
parent 57b03dfca931b87573f74b581d097b1de4455527
author Dimitrije Dobrota < mail@dimitrijedobrota.com >
date Thu, 1 May 2025 15:37:55 +0200

Reimplement and test some standrard type_traits

Diffstat:
M include/based/template.hpp | +++
M include/based/type_traits.hpp | ++++++++++++++++++++++++++++++++++++++++++++++++++++++ ----------------------------
M test/CMakeLists.txt | +++++ -
M test/source/signature_test.cpp | +++++++++++++++++++++++++++++++++++++++++ -----------------------------------------
A test/source/standard_traits_test.cpp | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

5 files changed, 505 insertions(+), 270 deletions(-)


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

@@ -13,6 +13,9 @@

namespace based
{

template<typename T>
class error_template;

/* ----- Buffer used for Local Buffer Optimization ----- */

template<size_t size, size_t alignment = alignof(void*)>

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

@@ -10,6 +10,64 @@

namespace based
{

/* ----- Standard Traits ----- */

template<typename...>
using void_t = void;

template<class T, T v>
struct integral_constant
{
static constexpr T value = v;

using value_type = T;
using type = integral_constant;

// NOLINTNEXTLINE explicit
constexpr operator value_type() const noexcept { return value; }
constexpr value_type operator()() const noexcept { return value; }
};

using true_type = integral_constant<bool, true>;
using false_type = integral_constant<bool, false>;

// clang-format off

template<class T, class U> struct is_same : false_type { };
template<class T> struct is_same<T, T> : true_type { };
template<class T, class U> constexpr bool is_same_v = is_same<T, U>::value;

template<class T> struct remove_reference { using type = T; };
template<class T> struct remove_reference<T&> { using type = T; };
template<class T> struct remove_reference<T&&> { using type = T; };
template<class T> using remove_reference_t = typename remove_reference<T>::type;

template<class T> struct remove_cv { using type = T; };
template<class T> struct remove_cv<const T> { using type = T; };
template<class T> struct remove_cv<volatile T> { using type = T; };
template<class T> struct remove_cv<const volatile T> { using type = T; };
template<class T> using remove_cv_t = typename remove_cv<T>::type;

template<class T> struct remove_const { using type = T; };
template<class T> struct remove_const<const T> { using type = T; };
template<class T> using remove_const_t = typename remove_const<T>::type;

template<class T> struct remove_volatile { using type = T; };
template<class T> struct remove_volatile<volatile T> { using type = T; };
template<class T> using remove_volatile_t = typename remove_volatile<T>::type;

template<class T> struct remove_cvref { using type = remove_cv_t<remove_reference_t<T>>; };
template<class T> using remove_cvref_t = typename remove_cvref<T>::type;

template<class T> struct remove_pointer { using type = T; };
template<class T> struct remove_pointer<T*> { using type = T; };
template<class T> struct remove_pointer<T* const> { using type = T; };
template<class T> struct remove_pointer<T* volatile> { using type = T; };
template<class T> struct remove_pointer<T* const volatile> { using type = T; };
template<class T> using remove_pointer_t = typename remove_pointer<T>::type;

// clang-format on

/* ----- Integer ----- */

template<typename T>

@@ -29,7 +87,7 @@ concept Integer = requires(T n) {

/* ----- Regular ----- */

template<typename T>
using bare_t = std::remove_cvref_t<T>;
using bare_t = remove_cvref_t<T>;

template<typename T>
concept Regular = std::regular<T>;

@@ -38,7 +96,7 @@ template<typename T>

concept BareRegular = std::regular<bare_t<T>>;

template<typename T, typename U>
concept SameAs = std::is_same_v<T, U> && std::is_same_v<U, T>;
concept SameAs = is_same_v<T, U> && is_same_v<U, T>;

template<typename T, typename U>
concept BareSameAs = SameAs<bare_t<T>, bare_t<U>>;

@@ -130,7 +188,17 @@ struct signature<Ret(Args...) noexcept(ne)>

using arg_type = std::tuple<Args...>;
using ret_type = Ret;

using noexcept_val = std::integral_constant<bool, ne>;
using noexcept_val = integral_constant<bool, ne>;
};

template<typename Ret, bool ne, typename... Args>
struct signature<Ret (*)(Args...) noexcept(ne)>
{
using sig_type = Ret(Args...);
using arg_type = std::tuple<Args...>;
using ret_type = Ret;

using noexcept_val = integral_constant<bool, ne>;
};

template<typename Ret, typename Obj, bool ne, typename... Args>

@@ -140,13 +208,13 @@ struct signature<Ret (Obj::*)(Args...) noexcept(ne)>

using arg_type = std::tuple<Args...>;
using ret_type = Ret;

using const_val = std::false_type;
using volatile_val = std::false_type;
using const_val = false_type;
using volatile_val = false_type;

using lvalref_val = std::false_type;
using rvalref_val = std::false_type;
using lvalref_val = false_type;
using rvalref_val = false_type;

using noexcept_val = std::integral_constant<bool, ne>;
using noexcept_val = integral_constant<bool, ne>;
};

template<typename Ret, typename Obj, bool ne, typename... Args>

@@ -156,13 +224,13 @@ struct signature<Ret (Obj::*)(Args...) & noexcept(ne)>

using arg_type = std::tuple<Args...>;
using ret_type = Ret;

using const_val = std::false_type;
using volatile_val = std::false_type;
using const_val = false_type;
using volatile_val = false_type;

using lvalref_val = std::true_type;
using rvalref_val = std::false_type;
using lvalref_val = true_type;
using rvalref_val = false_type;

using noexcept_val = std::integral_constant<bool, ne>;
using noexcept_val = integral_constant<bool, ne>;
};

template<typename Ret, typename Obj, bool ne, typename... Args>

@@ -172,13 +240,13 @@ struct signature<Ret (Obj::*)(Args...) && noexcept(ne)>

using arg_type = std::tuple<Args...>;
using ret_type = Ret;

using const_val = std::false_type;
using volatile_val = std::false_type;
using const_val = false_type;
using volatile_val = false_type;

using lvalref_val = std::false_type;
using rvalref_val = std::true_type;
using lvalref_val = false_type;
using rvalref_val = true_type;

using noexcept_val = std::integral_constant<bool, ne>;
using noexcept_val = integral_constant<bool, ne>;
};

template<typename Ret, typename Obj, bool ne, typename... Args>

@@ -188,13 +256,13 @@ struct signature<Ret (Obj::*)(Args...) const noexcept(ne)>

using arg_type = std::tuple<Args...>;
using ret_type = Ret;

using const_val = std::true_type;
using volatile_val = std::false_type;
using const_val = true_type;
using volatile_val = false_type;

using lvalref_val = std::false_type;
using rvalref_val = std::false_type;
using lvalref_val = false_type;
using rvalref_val = false_type;

using noexcept_val = std::integral_constant<bool, ne>;
using noexcept_val = integral_constant<bool, ne>;
};

template<typename Ret, typename Obj, bool ne, typename... Args>

@@ -204,13 +272,13 @@ struct signature<Ret (Obj::*)(Args...) const & noexcept(ne)>

using arg_type = std::tuple<Args...>;
using ret_type = Ret;

using const_val = std::true_type;
using volatile_val = std::false_type;
using const_val = true_type;
using volatile_val = false_type;

using lvalref_val = std::true_type;
using rvalref_val = std::false_type;
using lvalref_val = true_type;
using rvalref_val = false_type;

using noexcept_val = std::integral_constant<bool, ne>;
using noexcept_val = integral_constant<bool, ne>;
};

template<typename Ret, typename Obj, bool ne, typename... Args>

@@ -220,13 +288,13 @@ struct signature<Ret (Obj::*)(Args...) const && noexcept(ne)>

using arg_type = std::tuple<Args...>;
using ret_type = Ret;

using const_val = std::true_type;
using volatile_val = std::false_type;
using const_val = true_type;
using volatile_val = false_type;

using lvalref_val = std::false_type;
using rvalref_val = std::true_type;
using lvalref_val = false_type;
using rvalref_val = true_type;

using noexcept_val = std::integral_constant<bool, ne>;
using noexcept_val = integral_constant<bool, ne>;
};

template<typename Ret, typename Obj, bool ne, typename... Args>

@@ -236,13 +304,13 @@ struct signature<Ret (Obj::*)(Args...) volatile noexcept(ne)>

using arg_type = std::tuple<Args...>;
using ret_type = Ret;

using const_val = std::false_type;
using volatile_val = std::true_type;
using const_val = false_type;
using volatile_val = true_type;

using lvalref_val = std::false_type;
using rvalref_val = std::false_type;
using lvalref_val = false_type;
using rvalref_val = false_type;

using noexcept_val = std::integral_constant<bool, ne>;
using noexcept_val = integral_constant<bool, ne>;
};

template<typename Ret, typename Obj, bool ne, typename... Args>

@@ -252,13 +320,13 @@ struct signature<Ret (Obj::*)(Args...) volatile & noexcept(ne)>

using arg_type = std::tuple<Args...>;
using ret_type = Ret;

using const_val = std::false_type;
using volatile_val = std::true_type;
using const_val = false_type;
using volatile_val = true_type;

using lvalref_val = std::true_type;
using rvalref_val = std::false_type;
using lvalref_val = true_type;
using rvalref_val = false_type;

using noexcept_val = std::integral_constant<bool, ne>;
using noexcept_val = integral_constant<bool, ne>;
};

template<typename Ret, typename Obj, bool ne, typename... Args>

@@ -268,13 +336,13 @@ struct signature<Ret (Obj::*)(Args...) volatile && noexcept(ne)>

using arg_type = std::tuple<Args...>;
using ret_type = Ret;

using const_val = std::false_type;
using volatile_val = std::true_type;
using const_val = false_type;
using volatile_val = true_type;

using lvalref_val = std::false_type;
using rvalref_val = std::true_type;
using lvalref_val = false_type;
using rvalref_val = true_type;

using noexcept_val = std::integral_constant<bool, ne>;
using noexcept_val = integral_constant<bool, ne>;
};

template<typename Ret, typename Obj, bool ne, typename... Args>

@@ -284,13 +352,13 @@ struct signature<Ret (Obj::*)(Args...) const volatile noexcept(ne)>

using arg_type = std::tuple<Args...>;
using ret_type = Ret;

using const_val = std::true_type;
using volatile_val = std::true_type;
using const_val = true_type;
using volatile_val = true_type;

using lvalref_val = std::false_type;
using rvalref_val = std::false_type;
using lvalref_val = false_type;
using rvalref_val = false_type;

using noexcept_val = std::integral_constant<bool, ne>;
using noexcept_val = integral_constant<bool, ne>;
};

template<typename Ret, typename Obj, bool ne, typename... Args>

@@ -300,13 +368,13 @@ struct signature<Ret (Obj::*)(Args...) const volatile & noexcept(ne)>

using arg_type = std::tuple<Args...>;
using ret_type = Ret;

using const_val = std::true_type;
using volatile_val = std::true_type;
using const_val = true_type;
using volatile_val = true_type;

using lvalref_val = std::true_type;
using rvalref_val = std::false_type;
using lvalref_val = true_type;
using rvalref_val = false_type;

using noexcept_val = std::integral_constant<bool, ne>;
using noexcept_val = integral_constant<bool, ne>;
};

template<typename Ret, typename Obj, bool ne, typename... Args>

@@ -316,13 +384,13 @@ struct signature<Ret (Obj::*)(Args...) const volatile && noexcept(ne)>

using arg_type = std::tuple<Args...>;
using ret_type = Ret;

using const_val = std::true_type;
using volatile_val = std::true_type;
using const_val = true_type;
using volatile_val = true_type;

using lvalref_val = std::false_type;
using rvalref_val = std::true_type;
using lvalref_val = false_type;
using rvalref_val = true_type;

using noexcept_val = std::integral_constant<bool, ne>;
using noexcept_val = integral_constant<bool, ne>;
};

template<typename StaticCallOp>

@@ -360,27 +428,27 @@ function(F) -> function<Sig>;

/* ----- Function Concepts ----- */

template<typename T>
concept Input = std::is_same_v<T, std::remove_cvref_t<std::remove_pointer_t<T>>>
|| std::is_const_v<std::remove_reference_t<T>>
|| std::is_const_v<std::remove_pointer_t<T>>;
concept Input = std::is_same_v<T, remove_cvref_t<remove_pointer_t<T>>>
|| std::is_const_v<remove_reference_t<T>>
|| std::is_const_v<remove_pointer_t<T>>;

template<std::size_t idx, typename... Args>
requires(idx < sizeof...(Args))
using elem_t = std::tuple_element_t<idx, std::tuple<Args...>>;

template<typename... Args>
concept RegularDomain = (Regular<std::remove_cvref_t<Args>> && ...);
concept RegularDomain = (Regular<remove_cvref_t<Args>> && ...);

template<typename... Args>
concept InputDomain = (Input<Args> && ...);

template<typename... Args>
concept HomogeneousDomain = (std::same_as<elem_t<0, Args...>, Args> && ...);
concept HomogeneousDomain = (SameAs<elem_t<0, Args...>, Args> && ...);

template<typename P, typename Ret, typename... Args>
concept Procedure = requires {
requires(std::invocable<P, Args...>);
requires(std::same_as<void, Ret> || std::same_as<Ret, std::invoke_result_t<P, Args...>>);
requires(SameAs<void, Ret> || SameAs<Ret, std::invoke_result_t<P, Args...>>);
};

template<typename P, typename Ret, typename Arg>

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

@@ -22,6 +22,11 @@ endfunction()


# ----- Algorithm -----

# ----- Type Traits -----

add_test(standard_traits_test)
add_test(signature_test)

## ----- Min and Max -----

add_test(min_test)

@@ -65,7 +70,6 @@ add_test(string_literal_test)


# ---- Template ----

add_test(signature_test)
add_test(buffer_test)
add_test(function_test)
add_test(scopeguard_test)

diff --git a/ test/source/signature_test.cpp b/ test/source/signature_test.cpp

@@ -22,22 +22,24 @@ int free_func_noexcept(const double& a, int&& b) noexcept(true


} // namespace

using based::SameAs;

TEST_CASE("free function", "[type_traits/signature]")
{
using sig = based::signature<decltype(free_func)>;
STATIC_REQUIRE(std::same_as<int(const double&, int&&), sig::sig_type>);
STATIC_REQUIRE(std::same_as<std::tuple<const double&, int&&>, sig::arg_type>);
STATIC_REQUIRE(std::same_as<int, sig::ret_type>);
STATIC_REQUIRE(std::same_as<std::false_type, sig::noexcept_val>);
STATIC_REQUIRE(SameAs<int(const double&, int&&), sig::sig_type>);
STATIC_REQUIRE(SameAs<std::tuple<const double&, int&&>, sig::arg_type>);
STATIC_REQUIRE(SameAs<int, sig::ret_type>);
STATIC_REQUIRE(SameAs<based::false_type, sig::noexcept_val>);
}

TEST_CASE("free function noexcept", "[type_traits/signature]")
{
using sig = based::signature<decltype(free_func_noexcept)>;
STATIC_REQUIRE(std::same_as<int(const double&, int&&), sig::sig_type>);
STATIC_REQUIRE(std::same_as<std::tuple<const double&, int&&>, sig::arg_type>);
STATIC_REQUIRE(std::same_as<int, sig::ret_type>);
STATIC_REQUIRE(std::same_as<std::true_type, sig::noexcept_val>);
STATIC_REQUIRE(SameAs<int(const double&, int&&), sig::sig_type>);
STATIC_REQUIRE(SameAs<std::tuple<const double&, int&&>, sig::arg_type>);
STATIC_REQUIRE(SameAs<int, sig::ret_type>);
STATIC_REQUIRE(SameAs<based::true_type, sig::noexcept_val>);
}

TEST_CASE("empty", "[type_traits/signature]")

@@ -48,14 +50,14 @@ TEST_CASE("empty", "[type_traits/signature]")

};

using sig = based::signature<decltype(&test::func)>;
STATIC_REQUIRE(std::same_as<int(const double&, int&&), sig::sig_type>);
STATIC_REQUIRE(std::same_as<std::tuple<const double&, int&&>, sig::arg_type>);
STATIC_REQUIRE(std::same_as<int, sig::ret_type>);
STATIC_REQUIRE(std::same_as<std::false_type, sig::const_val>);
STATIC_REQUIRE(std::same_as<std::false_type, sig::volatile_val>);
STATIC_REQUIRE(std::same_as<std::false_type, sig::lvalref_val>);
STATIC_REQUIRE(std::same_as<std::false_type, sig::rvalref_val>);
STATIC_REQUIRE(std::same_as<std::false_type, sig::noexcept_val>);
STATIC_REQUIRE(SameAs<int(const double&, int&&), sig::sig_type>);
STATIC_REQUIRE(SameAs<std::tuple<const double&, int&&>, sig::arg_type>);
STATIC_REQUIRE(SameAs<int, sig::ret_type>);
STATIC_REQUIRE(SameAs<based::false_type, sig::const_val>);
STATIC_REQUIRE(SameAs<based::false_type, sig::volatile_val>);
STATIC_REQUIRE(SameAs<based::false_type, sig::lvalref_val>);
STATIC_REQUIRE(SameAs<based::false_type, sig::rvalref_val>);
STATIC_REQUIRE(SameAs<based::false_type, sig::noexcept_val>);
}

TEST_CASE("const", "[type_traits/signature]")

@@ -66,14 +68,14 @@ TEST_CASE("const", "[type_traits/signature]")

};

using sig = based::signature<decltype(&test::func)>;
STATIC_REQUIRE(std::same_as<int(const double&, int&&), sig::sig_type>);
STATIC_REQUIRE(std::same_as<std::tuple<const double&, int&&>, sig::arg_type>);
STATIC_REQUIRE(std::same_as<int, sig::ret_type>);
STATIC_REQUIRE(std::same_as<std::true_type, sig::const_val>);
STATIC_REQUIRE(std::same_as<std::false_type, sig::volatile_val>);
STATIC_REQUIRE(std::same_as<std::false_type, sig::lvalref_val>);
STATIC_REQUIRE(std::same_as<std::false_type, sig::rvalref_val>);
STATIC_REQUIRE(std::same_as<std::false_type, sig::noexcept_val>);
STATIC_REQUIRE(SameAs<int(const double&, int&&), sig::sig_type>);
STATIC_REQUIRE(SameAs<std::tuple<const double&, int&&>, sig::arg_type>);
STATIC_REQUIRE(SameAs<int, sig::ret_type>);
STATIC_REQUIRE(SameAs<based::true_type, sig::const_val>);
STATIC_REQUIRE(SameAs<based::false_type, sig::volatile_val>);
STATIC_REQUIRE(SameAs<based::false_type, sig::lvalref_val>);
STATIC_REQUIRE(SameAs<based::false_type, sig::rvalref_val>);
STATIC_REQUIRE(SameAs<based::false_type, sig::noexcept_val>);
}

TEST_CASE("volatile", "[type_traits/signature]")

@@ -84,14 +86,14 @@ TEST_CASE("volatile", "[type_traits/signature]")

};

using sig = based::signature<decltype(&test::func)>;
STATIC_REQUIRE(std::same_as<int(const double&, int&&), sig::sig_type>);
STATIC_REQUIRE(std::same_as<std::tuple<const double&, int&&>, sig::arg_type>);
STATIC_REQUIRE(std::same_as<int, sig::ret_type>);
STATIC_REQUIRE(std::same_as<std::false_type, sig::const_val>);
STATIC_REQUIRE(std::same_as<std::true_type, sig::volatile_val>);
STATIC_REQUIRE(std::same_as<std::false_type, sig::lvalref_val>);
STATIC_REQUIRE(std::same_as<std::false_type, sig::rvalref_val>);
STATIC_REQUIRE(std::same_as<std::false_type, sig::noexcept_val>);
STATIC_REQUIRE(SameAs<int(const double&, int&&), sig::sig_type>);
STATIC_REQUIRE(SameAs<std::tuple<const double&, int&&>, sig::arg_type>);
STATIC_REQUIRE(SameAs<int, sig::ret_type>);
STATIC_REQUIRE(SameAs<based::false_type, sig::const_val>);
STATIC_REQUIRE(SameAs<based::true_type, sig::volatile_val>);
STATIC_REQUIRE(SameAs<based::false_type, sig::lvalref_val>);
STATIC_REQUIRE(SameAs<based::false_type, sig::rvalref_val>);
STATIC_REQUIRE(SameAs<based::false_type, sig::noexcept_val>);
}

TEST_CASE("const volatile", "[type_traits/signature]")

@@ -102,14 +104,14 @@ TEST_CASE("const volatile", "[type_traits/signature]")

};

using sig = based::signature<decltype(&test::func)>;
STATIC_REQUIRE(std::same_as<int(const double&, int&&), sig::sig_type>);
STATIC_REQUIRE(std::same_as<std::tuple<const double&, int&&>, sig::arg_type>);
STATIC_REQUIRE(std::same_as<int, sig::ret_type>);
STATIC_REQUIRE(std::same_as<std::true_type, sig::const_val>);
STATIC_REQUIRE(std::same_as<std::true_type, sig::volatile_val>);
STATIC_REQUIRE(std::same_as<std::false_type, sig::lvalref_val>);
STATIC_REQUIRE(std::same_as<std::false_type, sig::rvalref_val>);
STATIC_REQUIRE(std::same_as<std::false_type, sig::noexcept_val>);
STATIC_REQUIRE(SameAs<int(const double&, int&&), sig::sig_type>);
STATIC_REQUIRE(SameAs<std::tuple<const double&, int&&>, sig::arg_type>);
STATIC_REQUIRE(SameAs<int, sig::ret_type>);
STATIC_REQUIRE(SameAs<based::true_type, sig::const_val>);
STATIC_REQUIRE(SameAs<based::true_type, sig::volatile_val>);
STATIC_REQUIRE(SameAs<based::false_type, sig::lvalref_val>);
STATIC_REQUIRE(SameAs<based::false_type, sig::rvalref_val>);
STATIC_REQUIRE(SameAs<based::false_type, sig::noexcept_val>);
}

TEST_CASE("noexcept", "[type_traits/signature]")

@@ -120,14 +122,14 @@ TEST_CASE("noexcept", "[type_traits/signature]")

};

using sig = based::signature<decltype(&test::func)>;
STATIC_REQUIRE(std::same_as<int(const double&, int&&), sig::sig_type>);
STATIC_REQUIRE(std::same_as<std::tuple<const double&, int&&>, sig::arg_type>);
STATIC_REQUIRE(std::same_as<int, sig::ret_type>);
STATIC_REQUIRE(std::same_as<std::false_type, sig::const_val>);
STATIC_REQUIRE(std::same_as<std::false_type, sig::volatile_val>);
STATIC_REQUIRE(std::same_as<std::false_type, sig::lvalref_val>);
STATIC_REQUIRE(std::same_as<std::false_type, sig::rvalref_val>);
STATIC_REQUIRE(std::same_as<std::true_type, sig::noexcept_val>);
STATIC_REQUIRE(SameAs<int(const double&, int&&), sig::sig_type>);
STATIC_REQUIRE(SameAs<std::tuple<const double&, int&&>, sig::arg_type>);
STATIC_REQUIRE(SameAs<int, sig::ret_type>);
STATIC_REQUIRE(SameAs<based::false_type, sig::const_val>);
STATIC_REQUIRE(SameAs<based::false_type, sig::volatile_val>);
STATIC_REQUIRE(SameAs<based::false_type, sig::lvalref_val>);
STATIC_REQUIRE(SameAs<based::false_type, sig::rvalref_val>);
STATIC_REQUIRE(SameAs<based::true_type, sig::noexcept_val>);
}

TEST_CASE("const noexcept", "[type_traits/signature]")

@@ -138,14 +140,14 @@ TEST_CASE("const noexcept", "[type_traits/signature]")

};

using sig = based::signature<decltype(&test::func)>;
STATIC_REQUIRE(std::same_as<int(const double&, int&&), sig::sig_type>);
STATIC_REQUIRE(std::same_as<std::tuple<const double&, int&&>, sig::arg_type>);
STATIC_REQUIRE(std::same_as<int, sig::ret_type>);
STATIC_REQUIRE(std::same_as<std::true_type, sig::const_val>);
STATIC_REQUIRE(std::same_as<std::false_type, sig::volatile_val>);
STATIC_REQUIRE(std::same_as<std::false_type, sig::lvalref_val>);
STATIC_REQUIRE(std::same_as<std::false_type, sig::rvalref_val>);
STATIC_REQUIRE(std::same_as<std::true_type, sig::noexcept_val>);
STATIC_REQUIRE(SameAs<int(const double&, int&&), sig::sig_type>);
STATIC_REQUIRE(SameAs<std::tuple<const double&, int&&>, sig::arg_type>);
STATIC_REQUIRE(SameAs<int, sig::ret_type>);
STATIC_REQUIRE(SameAs<based::true_type, sig::const_val>);
STATIC_REQUIRE(SameAs<based::false_type, sig::volatile_val>);
STATIC_REQUIRE(SameAs<based::false_type, sig::lvalref_val>);
STATIC_REQUIRE(SameAs<based::false_type, sig::rvalref_val>);
STATIC_REQUIRE(SameAs<based::true_type, sig::noexcept_val>);
}

TEST_CASE("volatile noexcept", "[type_traits/signature]")

@@ -156,14 +158,14 @@ TEST_CASE("volatile noexcept", "[type_traits/signature]")

};

using sig = based::signature<decltype(&test::func)>;
STATIC_REQUIRE(std::same_as<int(const double&, int&&), sig::sig_type>);
STATIC_REQUIRE(std::same_as<std::tuple<const double&, int&&>, sig::arg_type>);
STATIC_REQUIRE(std::same_as<int, sig::ret_type>);
STATIC_REQUIRE(std::same_as<std::false_type, sig::const_val>);
STATIC_REQUIRE(std::same_as<std::true_type, sig::volatile_val>);
STATIC_REQUIRE(std::same_as<std::false_type, sig::lvalref_val>);
STATIC_REQUIRE(std::same_as<std::false_type, sig::rvalref_val>);
STATIC_REQUIRE(std::same_as<std::true_type, sig::noexcept_val>);
STATIC_REQUIRE(SameAs<int(const double&, int&&), sig::sig_type>);
STATIC_REQUIRE(SameAs<std::tuple<const double&, int&&>, sig::arg_type>);
STATIC_REQUIRE(SameAs<int, sig::ret_type>);
STATIC_REQUIRE(SameAs<based::false_type, sig::const_val>);
STATIC_REQUIRE(SameAs<based::true_type, sig::volatile_val>);
STATIC_REQUIRE(SameAs<based::false_type, sig::lvalref_val>);
STATIC_REQUIRE(SameAs<based::false_type, sig::rvalref_val>);
STATIC_REQUIRE(SameAs<based::true_type, sig::noexcept_val>);
}

TEST_CASE("const volatile noexcept", "[type_traits/signature]")

@@ -174,14 +176,14 @@ TEST_CASE("const volatile noexcept", "[type_traits/signature]")

};

using sig = based::signature<decltype(&test::func)>;
STATIC_REQUIRE(std::same_as<int(const double&, int&&), sig::sig_type>);
STATIC_REQUIRE(std::same_as<std::tuple<const double&, int&&>, sig::arg_type>);
STATIC_REQUIRE(std::same_as<int, sig::ret_type>);
STATIC_REQUIRE(std::same_as<std::true_type, sig::const_val>);
STATIC_REQUIRE(std::same_as<std::true_type, sig::volatile_val>);
STATIC_REQUIRE(std::same_as<std::false_type, sig::lvalref_val>);
STATIC_REQUIRE(std::same_as<std::false_type, sig::rvalref_val>);
STATIC_REQUIRE(std::same_as<std::true_type, sig::noexcept_val>);
STATIC_REQUIRE(SameAs<int(const double&, int&&), sig::sig_type>);
STATIC_REQUIRE(SameAs<std::tuple<const double&, int&&>, sig::arg_type>);
STATIC_REQUIRE(SameAs<int, sig::ret_type>);
STATIC_REQUIRE(SameAs<based::true_type, sig::const_val>);
STATIC_REQUIRE(SameAs<based::true_type, sig::volatile_val>);
STATIC_REQUIRE(SameAs<based::false_type, sig::lvalref_val>);
STATIC_REQUIRE(SameAs<based::false_type, sig::rvalref_val>);
STATIC_REQUIRE(SameAs<based::true_type, sig::noexcept_val>);
}

TEST_CASE("lvalref", "[type_traits/signature]")

@@ -192,14 +194,14 @@ TEST_CASE("lvalref", "[type_traits/signature]")

};

using sig = based::signature<decltype(&test::func)>;
STATIC_REQUIRE(std::same_as<int(const double&, int&&), sig::sig_type>);
STATIC_REQUIRE(std::same_as<std::tuple<const double&, int&&>, sig::arg_type>);
STATIC_REQUIRE(std::same_as<int, sig::ret_type>);
STATIC_REQUIRE(std::same_as<std::false_type, sig::const_val>);
STATIC_REQUIRE(std::same_as<std::false_type, sig::volatile_val>);
STATIC_REQUIRE(std::same_as<std::true_type, sig::lvalref_val>);
STATIC_REQUIRE(std::same_as<std::false_type, sig::rvalref_val>);
STATIC_REQUIRE(std::same_as<std::false_type, sig::noexcept_val>);
STATIC_REQUIRE(SameAs<int(const double&, int&&), sig::sig_type>);
STATIC_REQUIRE(SameAs<std::tuple<const double&, int&&>, sig::arg_type>);
STATIC_REQUIRE(SameAs<int, sig::ret_type>);
STATIC_REQUIRE(SameAs<based::false_type, sig::const_val>);
STATIC_REQUIRE(SameAs<based::false_type, sig::volatile_val>);
STATIC_REQUIRE(SameAs<based::true_type, sig::lvalref_val>);
STATIC_REQUIRE(SameAs<based::false_type, sig::rvalref_val>);
STATIC_REQUIRE(SameAs<based::false_type, sig::noexcept_val>);
}

TEST_CASE("const lvalref", "[type_traits/signature]")

@@ -210,14 +212,14 @@ TEST_CASE("const lvalref", "[type_traits/signature]")

};

using sig = based::signature<decltype(&test::func)>;
STATIC_REQUIRE(std::same_as<int(const double&, int&&), sig::sig_type>);
STATIC_REQUIRE(std::same_as<std::tuple<const double&, int&&>, sig::arg_type>);
STATIC_REQUIRE(std::same_as<int, sig::ret_type>);
STATIC_REQUIRE(std::same_as<std::true_type, sig::const_val>);
STATIC_REQUIRE(std::same_as<std::false_type, sig::volatile_val>);
STATIC_REQUIRE(std::same_as<std::true_type, sig::lvalref_val>);
STATIC_REQUIRE(std::same_as<std::false_type, sig::rvalref_val>);
STATIC_REQUIRE(std::same_as<std::false_type, sig::noexcept_val>);
STATIC_REQUIRE(SameAs<int(const double&, int&&), sig::sig_type>);
STATIC_REQUIRE(SameAs<std::tuple<const double&, int&&>, sig::arg_type>);
STATIC_REQUIRE(SameAs<int, sig::ret_type>);
STATIC_REQUIRE(SameAs<based::true_type, sig::const_val>);
STATIC_REQUIRE(SameAs<based::false_type, sig::volatile_val>);
STATIC_REQUIRE(SameAs<based::true_type, sig::lvalref_val>);
STATIC_REQUIRE(SameAs<based::false_type, sig::rvalref_val>);
STATIC_REQUIRE(SameAs<based::false_type, sig::noexcept_val>);
}

TEST_CASE("volatile lvalref", "[type_traits/signature]")

@@ -228,14 +230,14 @@ TEST_CASE("volatile lvalref", "[type_traits/signature]")

};

using sig = based::signature<decltype(&test::func)>;
STATIC_REQUIRE(std::same_as<int(const double&, int&&), sig::sig_type>);
STATIC_REQUIRE(std::same_as<std::tuple<const double&, int&&>, sig::arg_type>);
STATIC_REQUIRE(std::same_as<int, sig::ret_type>);
STATIC_REQUIRE(std::same_as<std::false_type, sig::const_val>);
STATIC_REQUIRE(std::same_as<std::true_type, sig::volatile_val>);
STATIC_REQUIRE(std::same_as<std::true_type, sig::lvalref_val>);
STATIC_REQUIRE(std::same_as<std::false_type, sig::rvalref_val>);
STATIC_REQUIRE(std::same_as<std::false_type, sig::noexcept_val>);
STATIC_REQUIRE(SameAs<int(const double&, int&&), sig::sig_type>);
STATIC_REQUIRE(SameAs<std::tuple<const double&, int&&>, sig::arg_type>);
STATIC_REQUIRE(SameAs<int, sig::ret_type>);
STATIC_REQUIRE(SameAs<based::false_type, sig::const_val>);
STATIC_REQUIRE(SameAs<based::true_type, sig::volatile_val>);
STATIC_REQUIRE(SameAs<based::true_type, sig::lvalref_val>);
STATIC_REQUIRE(SameAs<based::false_type, sig::rvalref_val>);
STATIC_REQUIRE(SameAs<based::false_type, sig::noexcept_val>);
}

TEST_CASE("const volatile lvalref", "[type_traits/signature]")

@@ -246,14 +248,14 @@ TEST_CASE("const volatile lvalref", "[type_traits/signature]")

};

using sig = based::signature<decltype(&test::func)>;
STATIC_REQUIRE(std::same_as<int(const double&, int&&), sig::sig_type>);
STATIC_REQUIRE(std::same_as<std::tuple<const double&, int&&>, sig::arg_type>);
STATIC_REQUIRE(std::same_as<int, sig::ret_type>);
STATIC_REQUIRE(std::same_as<std::true_type, sig::const_val>);
STATIC_REQUIRE(std::same_as<std::true_type, sig::volatile_val>);
STATIC_REQUIRE(std::same_as<std::true_type, sig::lvalref_val>);
STATIC_REQUIRE(std::same_as<std::false_type, sig::rvalref_val>);
STATIC_REQUIRE(std::same_as<std::false_type, sig::noexcept_val>);
STATIC_REQUIRE(SameAs<int(const double&, int&&), sig::sig_type>);
STATIC_REQUIRE(SameAs<std::tuple<const double&, int&&>, sig::arg_type>);
STATIC_REQUIRE(SameAs<int, sig::ret_type>);
STATIC_REQUIRE(SameAs<based::true_type, sig::const_val>);
STATIC_REQUIRE(SameAs<based::true_type, sig::volatile_val>);
STATIC_REQUIRE(SameAs<based::true_type, sig::lvalref_val>);
STATIC_REQUIRE(SameAs<based::false_type, sig::rvalref_val>);
STATIC_REQUIRE(SameAs<based::false_type, sig::noexcept_val>);
}

TEST_CASE("noexcept lvalref", "[type_traits/signature]")

@@ -264,14 +266,14 @@ TEST_CASE("noexcept lvalref", "[type_traits/signature]")

};

using sig = based::signature<decltype(&test::func)>;
STATIC_REQUIRE(std::same_as<int(const double&, int&&), sig::sig_type>);
STATIC_REQUIRE(std::same_as<std::tuple<const double&, int&&>, sig::arg_type>);
STATIC_REQUIRE(std::same_as<int, sig::ret_type>);
STATIC_REQUIRE(std::same_as<std::false_type, sig::const_val>);
STATIC_REQUIRE(std::same_as<std::false_type, sig::volatile_val>);
STATIC_REQUIRE(std::same_as<std::true_type, sig::lvalref_val>);
STATIC_REQUIRE(std::same_as<std::false_type, sig::rvalref_val>);
STATIC_REQUIRE(std::same_as<std::true_type, sig::noexcept_val>);
STATIC_REQUIRE(SameAs<int(const double&, int&&), sig::sig_type>);
STATIC_REQUIRE(SameAs<std::tuple<const double&, int&&>, sig::arg_type>);
STATIC_REQUIRE(SameAs<int, sig::ret_type>);
STATIC_REQUIRE(SameAs<based::false_type, sig::const_val>);
STATIC_REQUIRE(SameAs<based::false_type, sig::volatile_val>);
STATIC_REQUIRE(SameAs<based::true_type, sig::lvalref_val>);
STATIC_REQUIRE(SameAs<based::false_type, sig::rvalref_val>);
STATIC_REQUIRE(SameAs<based::true_type, sig::noexcept_val>);
}

TEST_CASE("const noexcept lvalref", "[type_traits/signature]")

@@ -282,14 +284,14 @@ TEST_CASE("const noexcept lvalref", "[type_traits/signature]")

};

using sig = based::signature<decltype(&test::func)>;
STATIC_REQUIRE(std::same_as<int(const double&, int&&), sig::sig_type>);
STATIC_REQUIRE(std::same_as<std::tuple<const double&, int&&>, sig::arg_type>);
STATIC_REQUIRE(std::same_as<int, sig::ret_type>);
STATIC_REQUIRE(std::same_as<std::true_type, sig::const_val>);
STATIC_REQUIRE(std::same_as<std::false_type, sig::volatile_val>);
STATIC_REQUIRE(std::same_as<std::true_type, sig::lvalref_val>);
STATIC_REQUIRE(std::same_as<std::false_type, sig::rvalref_val>);
STATIC_REQUIRE(std::same_as<std::true_type, sig::noexcept_val>);
STATIC_REQUIRE(SameAs<int(const double&, int&&), sig::sig_type>);
STATIC_REQUIRE(SameAs<std::tuple<const double&, int&&>, sig::arg_type>);
STATIC_REQUIRE(SameAs<int, sig::ret_type>);
STATIC_REQUIRE(SameAs<based::true_type, sig::const_val>);
STATIC_REQUIRE(SameAs<based::false_type, sig::volatile_val>);
STATIC_REQUIRE(SameAs<based::true_type, sig::lvalref_val>);
STATIC_REQUIRE(SameAs<based::false_type, sig::rvalref_val>);
STATIC_REQUIRE(SameAs<based::true_type, sig::noexcept_val>);
}

TEST_CASE("volatile noexcept lvalref", "[type_traits/signature]")

@@ -300,14 +302,14 @@ TEST_CASE("volatile noexcept lvalref", "[type_traits/signature]")

};

using sig = based::signature<decltype(&test::func)>;
STATIC_REQUIRE(std::same_as<int(const double&, int&&), sig::sig_type>);
STATIC_REQUIRE(std::same_as<std::tuple<const double&, int&&>, sig::arg_type>);
STATIC_REQUIRE(std::same_as<int, sig::ret_type>);
STATIC_REQUIRE(std::same_as<std::false_type, sig::const_val>);
STATIC_REQUIRE(std::same_as<std::true_type, sig::volatile_val>);
STATIC_REQUIRE(std::same_as<std::true_type, sig::lvalref_val>);
STATIC_REQUIRE(std::same_as<std::false_type, sig::rvalref_val>);
STATIC_REQUIRE(std::same_as<std::true_type, sig::noexcept_val>);
STATIC_REQUIRE(SameAs<int(const double&, int&&), sig::sig_type>);
STATIC_REQUIRE(SameAs<std::tuple<const double&, int&&>, sig::arg_type>);
STATIC_REQUIRE(SameAs<int, sig::ret_type>);
STATIC_REQUIRE(SameAs<based::false_type, sig::const_val>);
STATIC_REQUIRE(SameAs<based::true_type, sig::volatile_val>);
STATIC_REQUIRE(SameAs<based::true_type, sig::lvalref_val>);
STATIC_REQUIRE(SameAs<based::false_type, sig::rvalref_val>);
STATIC_REQUIRE(SameAs<based::true_type, sig::noexcept_val>);
}

TEST_CASE("const volatile noexcept lvalref", "[type_traits/signature]")

@@ -318,14 +320,14 @@ TEST_CASE("const volatile noexcept lvalref", "[type_traits/signature]")

};

using sig = based::signature<decltype(&test::func)>;
STATIC_REQUIRE(std::same_as<int(const double&, int&&), sig::sig_type>);
STATIC_REQUIRE(std::same_as<std::tuple<const double&, int&&>, sig::arg_type>);
STATIC_REQUIRE(std::same_as<int, sig::ret_type>);
STATIC_REQUIRE(std::same_as<std::true_type, sig::const_val>);
STATIC_REQUIRE(std::same_as<std::true_type, sig::volatile_val>);
STATIC_REQUIRE(std::same_as<std::true_type, sig::lvalref_val>);
STATIC_REQUIRE(std::same_as<std::false_type, sig::rvalref_val>);
STATIC_REQUIRE(std::same_as<std::true_type, sig::noexcept_val>);
STATIC_REQUIRE(SameAs<int(const double&, int&&), sig::sig_type>);
STATIC_REQUIRE(SameAs<std::tuple<const double&, int&&>, sig::arg_type>);
STATIC_REQUIRE(SameAs<int, sig::ret_type>);
STATIC_REQUIRE(SameAs<based::true_type, sig::const_val>);
STATIC_REQUIRE(SameAs<based::true_type, sig::volatile_val>);
STATIC_REQUIRE(SameAs<based::true_type, sig::lvalref_val>);
STATIC_REQUIRE(SameAs<based::false_type, sig::rvalref_val>);
STATIC_REQUIRE(SameAs<based::true_type, sig::noexcept_val>);
}

TEST_CASE("rvalref", "[type_traits/signature]")

@@ -336,14 +338,14 @@ TEST_CASE("rvalref", "[type_traits/signature]")

};

using sig = based::signature<decltype(&test::func)>;
STATIC_REQUIRE(std::same_as<int(const double&, int&&), sig::sig_type>);
STATIC_REQUIRE(std::same_as<std::tuple<const double&, int&&>, sig::arg_type>);
STATIC_REQUIRE(std::same_as<int, sig::ret_type>);
STATIC_REQUIRE(std::same_as<std::false_type, sig::const_val>);
STATIC_REQUIRE(std::same_as<std::false_type, sig::volatile_val>);
STATIC_REQUIRE(std::same_as<std::false_type, sig::lvalref_val>);
STATIC_REQUIRE(std::same_as<std::true_type, sig::rvalref_val>);
STATIC_REQUIRE(std::same_as<std::false_type, sig::noexcept_val>);
STATIC_REQUIRE(SameAs<int(const double&, int&&), sig::sig_type>);
STATIC_REQUIRE(SameAs<std::tuple<const double&, int&&>, sig::arg_type>);
STATIC_REQUIRE(SameAs<int, sig::ret_type>);
STATIC_REQUIRE(SameAs<based::false_type, sig::const_val>);
STATIC_REQUIRE(SameAs<based::false_type, sig::volatile_val>);
STATIC_REQUIRE(SameAs<based::false_type, sig::lvalref_val>);
STATIC_REQUIRE(SameAs<based::true_type, sig::rvalref_val>);
STATIC_REQUIRE(SameAs<based::false_type, sig::noexcept_val>);
}

TEST_CASE("const rvalref", "[type_traits/signature]")

@@ -354,14 +356,14 @@ TEST_CASE("const rvalref", "[type_traits/signature]")

};

using sig = based::signature<decltype(&test::func)>;
STATIC_REQUIRE(std::same_as<int(const double&, int&&), sig::sig_type>);
STATIC_REQUIRE(std::same_as<std::tuple<const double&, int&&>, sig::arg_type>);
STATIC_REQUIRE(std::same_as<int, sig::ret_type>);
STATIC_REQUIRE(std::same_as<std::true_type, sig::const_val>);
STATIC_REQUIRE(std::same_as<std::false_type, sig::volatile_val>);
STATIC_REQUIRE(std::same_as<std::false_type, sig::lvalref_val>);
STATIC_REQUIRE(std::same_as<std::true_type, sig::rvalref_val>);
STATIC_REQUIRE(std::same_as<std::false_type, sig::noexcept_val>);
STATIC_REQUIRE(SameAs<int(const double&, int&&), sig::sig_type>);
STATIC_REQUIRE(SameAs<std::tuple<const double&, int&&>, sig::arg_type>);
STATIC_REQUIRE(SameAs<int, sig::ret_type>);
STATIC_REQUIRE(SameAs<based::true_type, sig::const_val>);
STATIC_REQUIRE(SameAs<based::false_type, sig::volatile_val>);
STATIC_REQUIRE(SameAs<based::false_type, sig::lvalref_val>);
STATIC_REQUIRE(SameAs<based::true_type, sig::rvalref_val>);
STATIC_REQUIRE(SameAs<based::false_type, sig::noexcept_val>);
}

TEST_CASE("volatile rvalref", "[type_traits/signature]")

@@ -372,14 +374,14 @@ TEST_CASE("volatile rvalref", "[type_traits/signature]")

};

using sig = based::signature<decltype(&test::func)>;
STATIC_REQUIRE(std::same_as<int(const double&, int&&), sig::sig_type>);
STATIC_REQUIRE(std::same_as<std::tuple<const double&, int&&>, sig::arg_type>);
STATIC_REQUIRE(std::same_as<int, sig::ret_type>);
STATIC_REQUIRE(std::same_as<std::false_type, sig::const_val>);
STATIC_REQUIRE(std::same_as<std::true_type, sig::volatile_val>);
STATIC_REQUIRE(std::same_as<std::false_type, sig::lvalref_val>);
STATIC_REQUIRE(std::same_as<std::true_type, sig::rvalref_val>);
STATIC_REQUIRE(std::same_as<std::false_type, sig::noexcept_val>);
STATIC_REQUIRE(SameAs<int(const double&, int&&), sig::sig_type>);
STATIC_REQUIRE(SameAs<std::tuple<const double&, int&&>, sig::arg_type>);
STATIC_REQUIRE(SameAs<int, sig::ret_type>);
STATIC_REQUIRE(SameAs<based::false_type, sig::const_val>);
STATIC_REQUIRE(SameAs<based::true_type, sig::volatile_val>);
STATIC_REQUIRE(SameAs<based::false_type, sig::lvalref_val>);
STATIC_REQUIRE(SameAs<based::true_type, sig::rvalref_val>);
STATIC_REQUIRE(SameAs<based::false_type, sig::noexcept_val>);
}

TEST_CASE("const volatile rvalref", "[type_traits/signature]")

@@ -390,14 +392,14 @@ TEST_CASE("const volatile rvalref", "[type_traits/signature]")

};

using sig = based::signature<decltype(&test::func)>;
STATIC_REQUIRE(std::same_as<int(const double&, int&&), sig::sig_type>);
STATIC_REQUIRE(std::same_as<std::tuple<const double&, int&&>, sig::arg_type>);
STATIC_REQUIRE(std::same_as<int, sig::ret_type>);
STATIC_REQUIRE(std::same_as<std::true_type, sig::const_val>);
STATIC_REQUIRE(std::same_as<std::true_type, sig::volatile_val>);
STATIC_REQUIRE(std::same_as<std::false_type, sig::lvalref_val>);
STATIC_REQUIRE(std::same_as<std::true_type, sig::rvalref_val>);
STATIC_REQUIRE(std::same_as<std::false_type, sig::noexcept_val>);
STATIC_REQUIRE(SameAs<int(const double&, int&&), sig::sig_type>);
STATIC_REQUIRE(SameAs<std::tuple<const double&, int&&>, sig::arg_type>);
STATIC_REQUIRE(SameAs<int, sig::ret_type>);
STATIC_REQUIRE(SameAs<based::true_type, sig::const_val>);
STATIC_REQUIRE(SameAs<based::true_type, sig::volatile_val>);
STATIC_REQUIRE(SameAs<based::false_type, sig::lvalref_val>);
STATIC_REQUIRE(SameAs<based::true_type, sig::rvalref_val>);
STATIC_REQUIRE(SameAs<based::false_type, sig::noexcept_val>);
}

TEST_CASE("noexcept rvalref", "[type_traits/signature]")

@@ -408,14 +410,14 @@ TEST_CASE("noexcept rvalref", "[type_traits/signature]")

};

using sig = based::signature<decltype(&test::func)>;
STATIC_REQUIRE(std::same_as<int(const double&, int&&), sig::sig_type>);
STATIC_REQUIRE(std::same_as<std::tuple<const double&, int&&>, sig::arg_type>);
STATIC_REQUIRE(std::same_as<int, sig::ret_type>);
STATIC_REQUIRE(std::same_as<std::false_type, sig::const_val>);
STATIC_REQUIRE(std::same_as<std::false_type, sig::volatile_val>);
STATIC_REQUIRE(std::same_as<std::false_type, sig::lvalref_val>);
STATIC_REQUIRE(std::same_as<std::true_type, sig::rvalref_val>);
STATIC_REQUIRE(std::same_as<std::true_type, sig::noexcept_val>);
STATIC_REQUIRE(SameAs<int(const double&, int&&), sig::sig_type>);
STATIC_REQUIRE(SameAs<std::tuple<const double&, int&&>, sig::arg_type>);
STATIC_REQUIRE(SameAs<int, sig::ret_type>);
STATIC_REQUIRE(SameAs<based::false_type, sig::const_val>);
STATIC_REQUIRE(SameAs<based::false_type, sig::volatile_val>);
STATIC_REQUIRE(SameAs<based::false_type, sig::lvalref_val>);
STATIC_REQUIRE(SameAs<based::true_type, sig::rvalref_val>);
STATIC_REQUIRE(SameAs<based::true_type, sig::noexcept_val>);
}

TEST_CASE("const noexcept rvalref", "[type_traits/signature]")

@@ -426,14 +428,14 @@ TEST_CASE("const noexcept rvalref", "[type_traits/signature]")

};

using sig = based::signature<decltype(&test::func)>;
STATIC_REQUIRE(std::same_as<int(const double&, int&&), sig::sig_type>);
STATIC_REQUIRE(std::same_as<std::tuple<const double&, int&&>, sig::arg_type>);
STATIC_REQUIRE(std::same_as<int, sig::ret_type>);
STATIC_REQUIRE(std::same_as<std::true_type, sig::const_val>);
STATIC_REQUIRE(std::same_as<std::false_type, sig::volatile_val>);
STATIC_REQUIRE(std::same_as<std::false_type, sig::lvalref_val>);
STATIC_REQUIRE(std::same_as<std::true_type, sig::rvalref_val>);
STATIC_REQUIRE(std::same_as<std::true_type, sig::noexcept_val>);
STATIC_REQUIRE(SameAs<int(const double&, int&&), sig::sig_type>);
STATIC_REQUIRE(SameAs<std::tuple<const double&, int&&>, sig::arg_type>);
STATIC_REQUIRE(SameAs<int, sig::ret_type>);
STATIC_REQUIRE(SameAs<based::true_type, sig::const_val>);
STATIC_REQUIRE(SameAs<based::false_type, sig::volatile_val>);
STATIC_REQUIRE(SameAs<based::false_type, sig::lvalref_val>);
STATIC_REQUIRE(SameAs<based::true_type, sig::rvalref_val>);
STATIC_REQUIRE(SameAs<based::true_type, sig::noexcept_val>);
}

TEST_CASE("volatile noexcept rvalref", "[type_traits/signature]")

@@ -444,14 +446,14 @@ TEST_CASE("volatile noexcept rvalref", "[type_traits/signature]")

};

using sig = based::signature<decltype(&test::func)>;
STATIC_REQUIRE(std::same_as<int(const double&, int&&), sig::sig_type>);
STATIC_REQUIRE(std::same_as<std::tuple<const double&, int&&>, sig::arg_type>);
STATIC_REQUIRE(std::same_as<int, sig::ret_type>);
STATIC_REQUIRE(std::same_as<std::false_type, sig::const_val>);
STATIC_REQUIRE(std::same_as<std::true_type, sig::volatile_val>);
STATIC_REQUIRE(std::same_as<std::false_type, sig::lvalref_val>);
STATIC_REQUIRE(std::same_as<std::true_type, sig::rvalref_val>);
STATIC_REQUIRE(std::same_as<std::true_type, sig::noexcept_val>);
STATIC_REQUIRE(SameAs<int(const double&, int&&), sig::sig_type>);
STATIC_REQUIRE(SameAs<std::tuple<const double&, int&&>, sig::arg_type>);
STATIC_REQUIRE(SameAs<int, sig::ret_type>);
STATIC_REQUIRE(SameAs<based::false_type, sig::const_val>);
STATIC_REQUIRE(SameAs<based::true_type, sig::volatile_val>);
STATIC_REQUIRE(SameAs<based::false_type, sig::lvalref_val>);
STATIC_REQUIRE(SameAs<based::true_type, sig::rvalref_val>);
STATIC_REQUIRE(SameAs<based::true_type, sig::noexcept_val>);
}

TEST_CASE("const volatile noexcept rvalref", "[type_traits/signature]")

@@ -462,14 +464,14 @@ TEST_CASE("const volatile noexcept rvalref", "[type_traits/signature]")

};

using sig = based::signature<decltype(&test::func)>;
STATIC_REQUIRE(std::same_as<int(const double&, int&&), sig::sig_type>);
STATIC_REQUIRE(std::same_as<std::tuple<const double&, int&&>, sig::arg_type>);
STATIC_REQUIRE(std::same_as<int, sig::ret_type>);
STATIC_REQUIRE(std::same_as<std::true_type, sig::const_val>);
STATIC_REQUIRE(std::same_as<std::true_type, sig::volatile_val>);
STATIC_REQUIRE(std::same_as<std::false_type, sig::lvalref_val>);
STATIC_REQUIRE(std::same_as<std::true_type, sig::rvalref_val>);
STATIC_REQUIRE(std::same_as<std::true_type, sig::noexcept_val>);
STATIC_REQUIRE(SameAs<int(const double&, int&&), sig::sig_type>);
STATIC_REQUIRE(SameAs<std::tuple<const double&, int&&>, sig::arg_type>);
STATIC_REQUIRE(SameAs<int, sig::ret_type>);
STATIC_REQUIRE(SameAs<based::true_type, sig::const_val>);
STATIC_REQUIRE(SameAs<based::true_type, sig::volatile_val>);
STATIC_REQUIRE(SameAs<based::false_type, sig::lvalref_val>);
STATIC_REQUIRE(SameAs<based::true_type, sig::rvalref_val>);
STATIC_REQUIRE(SameAs<based::true_type, sig::noexcept_val>);
}

// NOLINTEND cognitive-complexity

diff --git a/ test/source/standard_traits_test.cpp b/ test/source/standard_traits_test.cpp

@@ -0,0 +1,158 @@

// #define CATCH_CONFIG_RUNTIME_STATIC_REQUIRE

#include <catch2/catch_test_macros.hpp>

#include "based/type_traits.hpp"

// NOLINTBEGIN array

using based::SameAs;

TEST_CASE("remove_const", "[type_traits/remove_const]")
{
// clang-format off
STATIC_REQUIRE(SameAs<based::remove_const_t<int>, int>);
STATIC_REQUIRE(SameAs<based::remove_const_t<int&>, int&>);
STATIC_REQUIRE(SameAs<based::remove_const_t<int&&>, int&&>);
STATIC_REQUIRE(SameAs<based::remove_const_t<int[2]>, int[2]>);
STATIC_REQUIRE(SameAs<based::remove_const_t<int(&)[2]>, int(&)[2]>);
STATIC_REQUIRE(SameAs<based::remove_const_t<int(&&)[2]>, int(&&)[2]>);
STATIC_REQUIRE(SameAs<based::remove_const_t<const int>, int>);
STATIC_REQUIRE(SameAs<based::remove_const_t<const int&>, const int&>);
STATIC_REQUIRE(SameAs<based::remove_const_t<const int[2]>, int[2]>);
STATIC_REQUIRE(SameAs<based::remove_const_t<const int(&)[2]>, const int(&)[2]>);
STATIC_REQUIRE(SameAs<based::remove_const_t<int(int)>, int(int)>);
STATIC_REQUIRE(SameAs<based::remove_const_t<volatile int>, volatile int>);
STATIC_REQUIRE(SameAs<based::remove_const_t<volatile int&>, volatile int&>);
STATIC_REQUIRE(SameAs<based::remove_const_t<volatile int&&>, volatile int&&>);
STATIC_REQUIRE(SameAs<based::remove_const_t<volatile int[2]>, volatile int[2]>);
STATIC_REQUIRE(SameAs<based::remove_const_t<volatile int(&)[2]>, volatile int(&)[2]>);
STATIC_REQUIRE(SameAs<based::remove_const_t<volatile int(&&)[2]>, volatile int(&&)[2]>);
STATIC_REQUIRE(SameAs<based::remove_const_t<const volatile int>, volatile int>);
STATIC_REQUIRE(SameAs<based::remove_const_t<const volatile int&>, volatile const int&>);
STATIC_REQUIRE(SameAs<based::remove_const_t<const volatile int[2]>, volatile int[2]>);
STATIC_REQUIRE(SameAs<based::remove_const_t<const volatile int(&)[2]>, volatile const int(&)[2]>);
// clang-format on
}

TEST_CASE("remove_volatile", "[type_traits/remove_volatile]")
{
// clang-format off
STATIC_REQUIRE(SameAs<based::remove_volatile_t<int>, int>);
STATIC_REQUIRE(SameAs<based::remove_volatile_t<int&>, int&>);
STATIC_REQUIRE(SameAs<based::remove_volatile_t<int&&>, int&&>);
STATIC_REQUIRE(SameAs<based::remove_volatile_t<int[2]>, int[2]>);
STATIC_REQUIRE(SameAs<based::remove_volatile_t<int(&)[2]>, int(&)[2]>);
STATIC_REQUIRE(SameAs<based::remove_volatile_t<int(&&)[2]>, int(&&)[2]>);
STATIC_REQUIRE(SameAs<based::remove_volatile_t<const int>, const int>);
STATIC_REQUIRE(SameAs<based::remove_volatile_t<const int&>, const int&>);
STATIC_REQUIRE(SameAs<based::remove_volatile_t<const int[2]>, const int[2]>);
STATIC_REQUIRE(SameAs<based::remove_volatile_t<const int(&)[2]>, const int(&)[2]>);
STATIC_REQUIRE(SameAs<based::remove_volatile_t<int(int)>, int(int)>);
STATIC_REQUIRE(SameAs<based::remove_volatile_t<volatile int>, int>);
STATIC_REQUIRE(SameAs<based::remove_volatile_t<volatile int&>, volatile int&>);
STATIC_REQUIRE(SameAs<based::remove_volatile_t<volatile int&&>, volatile int&&>);
STATIC_REQUIRE(SameAs<based::remove_volatile_t<volatile int[2]>, int[2]>);
STATIC_REQUIRE(SameAs<based::remove_volatile_t<volatile int(&)[2]>, volatile int(&)[2]>);
STATIC_REQUIRE(SameAs<based::remove_volatile_t<volatile int(&&)[2]>, volatile int(&&)[2]>);
STATIC_REQUIRE(SameAs<based::remove_volatile_t<const volatile int>, const int>);
STATIC_REQUIRE(SameAs<based::remove_volatile_t<const volatile int&>, volatile const int&>);
STATIC_REQUIRE(SameAs<based::remove_volatile_t<const volatile int[2]>, const int[2]>);
STATIC_REQUIRE(SameAs<based::remove_volatile_t<const volatile int(&)[2]>, volatile const int(&)[2]>);
// clang-format on
}

TEST_CASE("remove_cv", "[type_traits/remove_cv]")
{
// clang-format off
STATIC_REQUIRE(SameAs<based::remove_cv_t<int>, int>);
STATIC_REQUIRE(SameAs<based::remove_cv_t<int&>, int&>);
STATIC_REQUIRE(SameAs<based::remove_cv_t<int&&>, int&&>);
STATIC_REQUIRE(SameAs<based::remove_cv_t<int[2]>, int[2]>);
STATIC_REQUIRE(SameAs<based::remove_cv_t<int(&)[2]>, int(&)[2]>);
STATIC_REQUIRE(SameAs<based::remove_cv_t<int(&&)[2]>, int(&&)[2]>);
STATIC_REQUIRE(SameAs<based::remove_cv_t<const int>, int>);
STATIC_REQUIRE(SameAs<based::remove_cv_t<const int&>, const int&>);
STATIC_REQUIRE(SameAs<based::remove_cv_t<const int[2]>, int[2]>);
STATIC_REQUIRE(SameAs<based::remove_cv_t<const int(&)[2]>, const int(&)[2]>);
STATIC_REQUIRE(SameAs<based::remove_cv_t<int(int)>, int(int)>);
STATIC_REQUIRE(SameAs<based::remove_cv_t<volatile int>, int>);
STATIC_REQUIRE(SameAs<based::remove_cv_t<volatile int&>, volatile int&>);
STATIC_REQUIRE(SameAs<based::remove_cv_t<volatile int&&>, volatile int&&>);
STATIC_REQUIRE(SameAs<based::remove_cv_t<volatile int[2]>, int[2]>);
STATIC_REQUIRE(SameAs<based::remove_cv_t<volatile int(&)[2]>, volatile int(&)[2]>);
STATIC_REQUIRE(SameAs<based::remove_cv_t<volatile int(&&)[2]>, volatile int(&&)[2]>);
STATIC_REQUIRE(SameAs<based::remove_cv_t<const volatile int>, int>);
STATIC_REQUIRE(SameAs<based::remove_cv_t<const volatile int&>, volatile const int&>);
STATIC_REQUIRE(SameAs<based::remove_cv_t<const volatile int[2]>, int[2]>);
STATIC_REQUIRE(SameAs<based::remove_cv_t<const volatile int(&)[2]>, volatile const int(&)[2]>);
// clang-format on
}

TEST_CASE("remove_reference", "[type_traits/remove_reference]")
{
// clang-format off
STATIC_REQUIRE(SameAs<based::remove_reference_t<int>, int>);
STATIC_REQUIRE(SameAs<based::remove_reference_t<int&>, int>);
STATIC_REQUIRE(SameAs<based::remove_reference_t<int&&>, int>);
STATIC_REQUIRE(SameAs<based::remove_reference_t<int[2]>, int[2]>);
STATIC_REQUIRE(SameAs<based::remove_reference_t<int(&)[2]>, int[2]>);
STATIC_REQUIRE(SameAs<based::remove_reference_t<int(&&)[2]>, int[2]>);
STATIC_REQUIRE(SameAs<based::remove_reference_t<const int>, const int>);
STATIC_REQUIRE(SameAs<based::remove_reference_t<const int&>, const int>);
STATIC_REQUIRE(SameAs<based::remove_reference_t<const int[2]>, const int[2]>);
STATIC_REQUIRE(SameAs<based::remove_reference_t<const int(&)[2]>, const int[2]>);
STATIC_REQUIRE(SameAs<based::remove_reference_t<int(int)>, int(int)>);
STATIC_REQUIRE(SameAs<based::remove_reference_t<volatile int>,volatile int>);
STATIC_REQUIRE(SameAs<based::remove_reference_t<volatile int&>, volatile int>);
STATIC_REQUIRE(SameAs<based::remove_reference_t<volatile int&&>, volatile int>);
STATIC_REQUIRE(SameAs<based::remove_reference_t<volatile int[2]>, volatile int[2]>);
STATIC_REQUIRE(SameAs<based::remove_reference_t<volatile int(&)[2]>, volatile int[2]>);
STATIC_REQUIRE(SameAs<based::remove_reference_t<volatile int(&&)[2]>, volatile int[2]>);
STATIC_REQUIRE(SameAs<based::remove_reference_t<const volatile int>, const volatile int>);
STATIC_REQUIRE(SameAs<based::remove_reference_t<const volatile int&>, volatile const int>);
STATIC_REQUIRE(SameAs<based::remove_reference_t<const volatile int[2]>, const volatile int[2]>);
STATIC_REQUIRE(SameAs<based::remove_reference_t<const volatile int(&)[2]>, volatile const int[2]>);
// clang-format on
}

TEST_CASE("remove_cvref", "[type_traits/remove_cvref]")
{
// clang-format off
STATIC_REQUIRE(SameAs<based::remove_cvref_t<int>, int>);
STATIC_REQUIRE(SameAs<based::remove_cvref_t<int&>, int>);
STATIC_REQUIRE(SameAs<based::remove_cvref_t<int&&>, int>);
STATIC_REQUIRE(SameAs<based::remove_cvref_t<int[2]>, int[2]>);
STATIC_REQUIRE(SameAs<based::remove_cvref_t<int(&)[2]>, int[2]>);
STATIC_REQUIRE(SameAs<based::remove_cvref_t<int(&&)[2]>, int[2]>);
STATIC_REQUIRE(SameAs<based::remove_cvref_t<const int>, int>);
STATIC_REQUIRE(SameAs<based::remove_cvref_t<const int&>, int>);
STATIC_REQUIRE(SameAs<based::remove_cvref_t<const int[2]>, int[2]>);
STATIC_REQUIRE(SameAs<based::remove_cvref_t<const int(&)[2]>, int[2]>);
STATIC_REQUIRE(SameAs<based::remove_cvref_t<int(int)>, int(int)>);
STATIC_REQUIRE(SameAs<based::remove_cvref_t<volatile int>, int>);
STATIC_REQUIRE(SameAs<based::remove_cvref_t<volatile int&>, int>);
STATIC_REQUIRE(SameAs<based::remove_cvref_t<volatile int&&>, int>);
STATIC_REQUIRE(SameAs<based::remove_cvref_t<volatile int[2]>, int[2]>);
STATIC_REQUIRE(SameAs<based::remove_cvref_t<volatile int(&)[2]>, int[2]>);
STATIC_REQUIRE(SameAs<based::remove_cvref_t<volatile int(&&)[2]>, int[2]>);
STATIC_REQUIRE(SameAs<based::remove_cvref_t<const volatile int>, int>);
STATIC_REQUIRE(SameAs<based::remove_cvref_t<const volatile int&>, int>);
STATIC_REQUIRE(SameAs<based::remove_cvref_t<const volatile int[2]>, int[2]>);
STATIC_REQUIRE(SameAs<based::remove_cvref_t<const volatile int(&)[2]>, int[2]>);
// clang-format on
}

TEST_CASE("remove_pointer", "[type_traits/remove_pointer]")
{
// clang-format off
STATIC_REQUIRE(SameAs<based::remove_pointer_t<int>, int>);
STATIC_REQUIRE(SameAs<based::remove_pointer_t<int*>, int>);
STATIC_REQUIRE(SameAs<based::remove_pointer_t<int**>, int*>);
STATIC_REQUIRE(SameAs<based::remove_pointer_t<int* const>, int>);
STATIC_REQUIRE(SameAs<based::remove_pointer_t<int* volatile>, int>);
STATIC_REQUIRE(SameAs<based::remove_pointer_t<int* const volatile>, int>);
// clang-format on
}

// NOLINTEND array