diff options
author | Steven Le Rouzic <steven.lerouzic@gmail.com> | 2024-08-15 00:58:37 +0200 |
---|---|---|
committer | Steven Le Rouzic <steven.lerouzic@gmail.com> | 2024-08-15 00:58:37 +0200 |
commit | 298ee421d9dcb6af3d29833f4cf636bb088356fb (patch) | |
tree | cd73df4683622283eff23b98d8bf096a8b86b234 /asl | |
parent | 75b10758ba116eabed730d23e957f1d69a1e3cb8 (diff) |
Some work on pointers
Diffstat (limited to 'asl')
-rw-r--r-- | asl/BUILD.bazel | 5 | ||||
-rw-r--r-- | asl/integers.hpp | 2 | ||||
-rw-r--r-- | asl/meta.hpp | 51 | ||||
-rw-r--r-- | asl/meta_tests.cpp | 41 | ||||
-rw-r--r-- | asl/object.hpp | 10 | ||||
-rw-r--r-- | asl/object_tests.cpp | 1 | ||||
-rw-r--r-- | asl/ptr.hpp | 106 | ||||
-rw-r--r-- | asl/ptr_tests.cpp | 12 | ||||
-rw-r--r-- | asl/utility.hpp | 4 |
9 files changed, 222 insertions, 10 deletions
diff --git a/asl/BUILD.bazel b/asl/BUILD.bazel index dc0aef8..710eaa8 100644 --- a/asl/BUILD.bazel +++ b/asl/BUILD.bazel @@ -3,6 +3,9 @@ cc_library( hdrs = [
"integers.hpp",
"meta.hpp",
+ "object.hpp",
+ "ptr.hpp",
+ "utility.hpp",
],
visibility = ["//visibility:public"],
)
@@ -15,4 +18,4 @@ cc_library( deps = [
":asl",
],
-) for name in ["integers", "meta"]]
+) for name in ["integers", "meta", "object", "ptr"]]
diff --git a/asl/integers.hpp b/asl/integers.hpp index 07fa11e..b5d3e99 100644 --- a/asl/integers.hpp +++ b/asl/integers.hpp @@ -10,3 +10,5 @@ using uint16_t = unsigned short; using uint32_t = unsigned int;
using uint64_t = unsigned long long;
+using isize_t = int64_t;
+
diff --git a/asl/meta.hpp b/asl/meta.hpp index 15f7790..c55500a 100644 --- a/asl/meta.hpp +++ b/asl/meta.hpp @@ -8,6 +8,11 @@ template<bool B> using bool_constant = integral_constant<bool, B>; using true_type = bool_constant<true>;
using false_type = bool_constant<false>;
+template<bool kSelect, typename U, typename V> struct _select_helper { using type = V; };
+template<typename U, typename V> struct _select_helper<true, U, V> { using type = U; };
+
+template<bool kSelect, typename U, typename V> using select_t = _select_helper<kSelect, U, V>::type;
+
using nullptr_t = decltype(nullptr);
template<typename T> struct un_ref { using type = T; };
@@ -84,6 +89,50 @@ template<typename T> concept is_member_object_ptr = is_member_ptr<T> && !is_memb template<typename T> concept is_fundamental = is_arithmetic<T> || is_void<T> || is_nullptr<T>;
template<typename T> concept is_compound = !is_fundamental<T>;
template<typename T> concept is_scalar = (is_fundamental<T> && !is_void<T>) || is_enum<T> || is_ptr<T> || is_member_ptr<T>;
-template<typename T> concept is_object = is_scalar<T> || is_array<T> || is_class<T> || is_union<T>;
+template<typename T> concept is_object = is_scalar<T> || is_class<T> || is_union<T>;
+
+template<typename T> concept is_empty = is_void<T> || __is_empty(T);
+
+struct empty {};
+
+template<typename T> using devoid_t = select_t<is_void<T>, empty, T>;
+
+template<typename F> struct _tame_helper { using type = F; };
+
+#define ASL_TAME_IMPL(SUFFIX) \
+ template<typename Ret, typename... Args> \
+ struct _tame_helper<Ret(Args...) SUFFIX> { using type = Ret(Args...); }
+
+ASL_TAME_IMPL();
+ASL_TAME_IMPL(const);
+ASL_TAME_IMPL(volatile);
+ASL_TAME_IMPL(volatile const);
+ASL_TAME_IMPL(&&);
+ASL_TAME_IMPL(const &&);
+ASL_TAME_IMPL(volatile &&);
+ASL_TAME_IMPL(volatile const &&);
+ASL_TAME_IMPL(&);
+ASL_TAME_IMPL(const &);
+ASL_TAME_IMPL(volatile &);
+ASL_TAME_IMPL(volatile const &);
+ASL_TAME_IMPL(noexcept);
+ASL_TAME_IMPL(const noexcept);
+ASL_TAME_IMPL(volatile noexcept);
+ASL_TAME_IMPL(volatile const noexcept);
+ASL_TAME_IMPL(&& noexcept);
+ASL_TAME_IMPL(const && noexcept);
+ASL_TAME_IMPL(volatile && noexcept);
+ASL_TAME_IMPL(volatile const && noexcept);
+ASL_TAME_IMPL(& noexcept);
+ASL_TAME_IMPL(const & noexcept);
+ASL_TAME_IMPL(volatile & noexcept);
+ASL_TAME_IMPL(volatile const & noexcept);
+
+#undef ASL_TAME_IMPL
+
+template<typename T> using tame_t = _tame_helper<T>::type;
+
+template<typename T> using as_raw_ptr_t = un_ref_t<tame_t<T>>*;
+
} // namespace asl
diff --git a/asl/meta_tests.cpp b/asl/meta_tests.cpp index f3d31f4..34603e6 100644 --- a/asl/meta_tests.cpp +++ b/asl/meta_tests.cpp @@ -1,5 +1,6 @@ #include "asl/meta.hpp"
+struct EmptyStruct {};
struct Struct { int b: 4; };
union Union {};
@@ -550,15 +551,15 @@ static_assert(asl::is_object<int Struct::*>); static_assert(asl::is_object<int (Struct::*)()>);
static_assert(!asl::is_object<int&>);
static_assert(!asl::is_object<int&&>);
-static_assert(asl::is_object<int[25]>);
-static_assert(asl::is_object<int[]>);
-static_assert(asl::is_object<int*[]>);
+static_assert(!asl::is_object<int[25]>);
+static_assert(!asl::is_object<int[]>);
+static_assert(!asl::is_object<int*[]>);
static_assert(!asl::is_object<int(&)[]>);
static_assert(asl::is_object<int(*)[]>);
-static_assert(asl::is_object<int[]>);
-static_assert(asl::is_object<Struct[4]>);
-static_assert(asl::is_object<Union[]>);
-static_assert(asl::is_object<Enum[]>);
+static_assert(!asl::is_object<int[]>);
+static_assert(!asl::is_object<Struct[4]>);
+static_assert(!asl::is_object<Union[]>);
+static_assert(!asl::is_object<Enum[]>);
static_assert(!asl::is_object<int()>);
static_assert(asl::is_object<Struct>);
static_assert(asl::is_object<const Struct>);
@@ -568,5 +569,29 @@ static_assert(asl::is_object<Union>); static_assert(asl::is_object<Enum>);
static_assert(asl::is_object<EnumClass>);
-int main() { return 0; }
+static_assert(asl::is_empty<void>);
+static_assert(!asl::is_empty<int>);
+static_assert(asl::is_empty<EmptyStruct>);
+static_assert(!asl::is_empty<Union>);
+static_assert(asl::is_empty<asl::empty>);
+
+static_assert(asl::is_same<asl::select_t<false, int, float>, float>);
+static_assert(asl::is_same<asl::select_t<true, int, float>, int>);
+
+static_assert(asl::is_same<asl::devoid_t<int>, int>);
+static_assert(asl::is_same<asl::devoid_t<void>, asl::empty>);
+static_assert(asl::is_same<asl::devoid_t<const void>, asl::empty>);
+static_assert(asl::is_same<asl::tame_t<int(float)>, int(float)>);
+static_assert(asl::is_same<asl::tame_t<int(float) &>, int(float)>);
+static_assert(asl::is_same<asl::tame_t<int(float) const &&>, int(float)>);
+static_assert(asl::is_same<asl::tame_t<int(float) volatile noexcept>, int(float)>);
+static_assert(asl::is_same<asl::tame_t<int(float) const>, int(float)>);
+static_assert(asl::is_same<asl::tame_t<int(float) const volatile & noexcept>, int(float)>);
+
+static_assert(asl::is_same<asl::as_raw_ptr_t<int>, int*>);
+static_assert(asl::is_same<asl::as_raw_ptr_t<const int>, const int*>);
+static_assert(asl::is_same<asl::as_raw_ptr_t<int(float)>, int(*)(float)>);
+static_assert(asl::is_same<asl::as_raw_ptr_t<int&>, int*>);
+
+int main() { return 0; }
diff --git a/asl/object.hpp b/asl/object.hpp new file mode 100644 index 0000000..17e9ce4 --- /dev/null +++ b/asl/object.hpp @@ -0,0 +1,10 @@ +#pragma once
+
+namespace asl {
+
+template<typename T>
+class object final
+{
+};
+
+} // namespace asl
diff --git a/asl/object_tests.cpp b/asl/object_tests.cpp new file mode 100644 index 0000000..2f38372 --- /dev/null +++ b/asl/object_tests.cpp @@ -0,0 +1 @@ +int main() { return 0; }
diff --git a/asl/ptr.hpp b/asl/ptr.hpp new file mode 100644 index 0000000..70dfa7b --- /dev/null +++ b/asl/ptr.hpp @@ -0,0 +1,106 @@ +#pragma once
+
+#include "asl/integers.hpp"
+#include "asl/meta.hpp"
+#include "asl/utility.hpp"
+
+namespace asl {
+
+namespace ptr_internal {
+
+template<is_object T>
+class object_meta
+{
+public:
+ using pointee = T;
+ using metadata = empty;
+};
+
+template<is_void T>
+class void_meta
+{
+public:
+ using pointee = T;
+ using metadata = empty;
+};
+
+template<typename T>
+class array_meta;
+
+template<is_object T, isize_t N>
+class array_meta<T[N]>
+{
+public:
+ using pointee = T[N];
+ using metadata = empty;
+};
+
+template<is_object T>
+class array_meta<T[]>
+{
+public:
+ using pointee = T;
+ using metadata = isize_t;
+};
+
+template<typename T>
+class ptr_like_meta
+{
+ static_assert(is_func<T> || is_ref<T>);
+
+public:
+ using pointee = as_raw_ptr_t<T>;
+ using metadata = empty;
+};
+
+template<typename T>
+constexpr auto get_meta()
+{
+ if constexpr (is_object<T>)
+ {
+ return object_meta<T>{};
+ }
+ else if constexpr (is_void<T>)
+ {
+ return void_meta<T>{};
+ }
+ else if constexpr (is_array<T>)
+ {
+ return array_meta<T>{};
+ }
+ else if constexpr (is_ref<T> || is_func<T>)
+ {
+ return ptr_like_meta<T>{};
+ }
+}
+
+template<typename T>
+using meta = decltype(get_meta<T>());
+
+} // namespace ptr_internal
+
+template<typename T>
+concept is_ptr_metadata = requires
+{
+ requires is_object<typename T::pointee> || is_void<typename T::pointee> || is_array<typename T::pointee>;
+ requires is_object<typename T::metadata>;
+};
+
+template<typename T>
+class ptr final
+{
+ using meta = ptr_internal::meta<T>;
+ static_assert(is_ptr_metadata<meta>);
+
+public:
+ using pointee = meta::pointee;
+ using metadata = meta::metadata;
+
+private:
+ pointee* m_ptr = nullptr;
+ ASL_NO_UNIQUE_ADDRESS metadata m_metadata;
+
+public:
+};
+
+} // namespace asl
diff --git a/asl/ptr_tests.cpp b/asl/ptr_tests.cpp new file mode 100644 index 0000000..316ae1d --- /dev/null +++ b/asl/ptr_tests.cpp @@ -0,0 +1,12 @@ +#include "asl/ptr.hpp"
+
+static_assert(sizeof(asl::ptr<int>) == sizeof(int*));
+static_assert(sizeof(asl::ptr<void>) == sizeof(void*));
+static_assert(sizeof(asl::ptr<int[]>) == 2 * sizeof(int*));
+static_assert(sizeof(asl::ptr<int[25]>) == sizeof(int*));
+static_assert(sizeof(asl::ptr<int*>) == sizeof(int**));
+static_assert(sizeof(asl::ptr<void(*)()>) == sizeof(void*));
+static_assert(sizeof(asl::ptr<void()>) == sizeof(void*));
+static_assert(sizeof(asl::ptr<int&>) == sizeof(int*));
+
+int main() { return 0; }
diff --git a/asl/utility.hpp b/asl/utility.hpp new file mode 100644 index 0000000..e8b9d86 --- /dev/null +++ b/asl/utility.hpp @@ -0,0 +1,4 @@ +#pragma once
+
+#define ASL_NO_UNIQUE_ADDRESS [[msvc::no_unique_address]]
+
|