summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSteven Le Rouzic <steven.lerouzic@gmail.com>2025-03-20 19:28:56 +0100
committerSteven Le Rouzic <steven.lerouzic@gmail.com>2025-03-20 19:29:08 +0100
commita665c590d5089bb4bcb72193542b60ef571409a3 (patch)
tree9e6a47c4332d25fcb64280bc0742d27b6a0f3291
parent7023c0cc9a7c6d2085f018d5524df6a726d6e487 (diff)
Add decay
-rw-r--r--asl/base/meta.hpp25
-rw-r--r--asl/base/meta_tests.cpp14
2 files changed, 35 insertions, 4 deletions
diff --git a/asl/base/meta.hpp b/asl/base/meta.hpp
index 8bebf2f..93e5603 100644
--- a/asl/base/meta.hpp
+++ b/asl/base/meta.hpp
@@ -54,6 +54,11 @@ template<typename T> using as_rref_t = decltype(_as_rref_helper<T>(0))::type;
template<typename T> consteval as_rref_t<T> declval() {}
+template<typename T> auto _as_ptr_helper(int) -> id<T*>;
+template<typename T> auto _as_ptr_helper(...) -> id<T>;
+
+template<typename T> using as_ptr_t = decltype(_as_ptr_helper<T>(0))::type;
+
template<typename T> struct _un_ref_t { using type = T; };
template<typename T> struct _un_ref_t<T&> { using type = T; };
template<typename T> struct _un_ref_t<T&&> { using type = T; };
@@ -191,11 +196,23 @@ template<typename T> concept is_func = _is_func_helper<tame_t<T>>::value;
template<typename T> concept is_object = !is_void<T> && !is_ref<T> && !is_func<T>;
-template<typename T> struct _is_array_helper : false_type {};
-template<typename T> struct _is_array_helper<T[]> : true_type {};
-template<typename T, int N> struct _is_array_helper<T[N]> : true_type {};
+template<typename T> struct _array_helper : false_type { using type = T; };
+template<typename T> struct _array_helper<T[]> : true_type { using type = T; };
+template<typename T, int N> struct _array_helper<T[N]> : true_type { using type = T; };
+
+template<typename T> concept is_array = _array_helper<T>::value;
-template<typename T> concept is_array = _is_array_helper<T>::value;
+template<typename T> using remove_extent_t = _array_helper<T>::type;
+
+template<typename T>
+using decay_t =
+ select_t<
+ is_array<un_ref_t<T>>,
+ as_ptr_t<remove_extent_t<un_ref_t<T>>>,
+ select_t<
+ is_func<un_ref_t<T>>,
+ as_ptr_t<un_ref_t<T>>,
+ un_cv_t<un_ref_t<T>>>>;
template<typename T> struct _is_floating_point_helper : false_type {};
template<> struct _is_floating_point_helper<float> : true_type {};
diff --git a/asl/base/meta_tests.cpp b/asl/base/meta_tests.cpp
index 490b453..bcd9775 100644
--- a/asl/base/meta_tests.cpp
+++ b/asl/base/meta_tests.cpp
@@ -189,6 +189,10 @@ static_assert(!asl::is_array<void>);
static_assert(!asl::is_array<void(int)>);
static_assert(!asl::is_array<int(float) const && noexcept>);
+static_assert(asl::same_as<int, asl::remove_extent_t<int>>);
+static_assert(asl::same_as<int, asl::remove_extent_t<int[]>>);
+static_assert(asl::same_as<int, asl::remove_extent_t<int[67]>>);
+
static_assert(asl::same_as<int, asl::un_ref_t<int>>);
static_assert(asl::same_as<int, asl::un_ref_t<int&>>);
static_assert(asl::same_as<int, asl::un_ref_t<int&&>>);
@@ -318,3 +322,13 @@ static_assert(asl::same_as<asl::copy_cref_t<const int&, const float>, const floa
static_assert(asl::same_as<asl::copy_cref_t<const int&, float&&>, const float&>);
static_assert(asl::same_as<asl::copy_cref_t<const int&, const float&>, const float&>);
+static_assert(asl::same_as<asl::decay_t<int>, int>);
+static_assert(!asl::same_as<asl::decay_t<int>, float>);
+static_assert(asl::same_as<asl::decay_t<int&>, int>);
+static_assert(asl::same_as<asl::decay_t<int&&>, int>);
+static_assert(asl::same_as<asl::decay_t<const int&>, int>);
+static_assert(asl::same_as<asl::decay_t<int[2]>, int*>);
+static_assert(!asl::same_as<asl::decay_t<int[4][2]>, int*>);
+static_assert(!asl::same_as<asl::decay_t<int[4][2]>, int**>);
+static_assert(asl::same_as<asl::decay_t<int[4][2]>, int(*)[2]>);
+static_assert(asl::same_as<asl::decay_t<int(int)>, int(*)(int)>);