summaryrefslogtreecommitdiff
path: root/asl
diff options
context:
space:
mode:
authorSteven Le Rouzic <steven.lerouzic@gmail.com>2025-02-25 23:25:14 +0100
committerSteven Le Rouzic <steven.lerouzic@gmail.com>2025-02-25 23:27:26 +0100
commitf165706505c214903f1743082d8ba1063c4fcfd3 (patch)
tree8807968b9f1f2185d7241a50879d2ca33f34566a /asl
parent507a994399c9ddf7e78bd4a290e05f54ddc2f3a6 (diff)
Add ASL_FWD_LIKE
Diffstat (limited to 'asl')
-rw-r--r--asl/base/utility.hpp2
-rw-r--r--asl/base/utility_tests.cpp79
2 files changed, 81 insertions, 0 deletions
diff --git a/asl/base/utility.hpp b/asl/base/utility.hpp
index b3fb36b..b8e13ae 100644
--- a/asl/base/utility.hpp
+++ b/asl/base/utility.hpp
@@ -7,6 +7,8 @@
#define ASL_FWD(expr_) (static_cast<decltype(expr_)&&>(expr_))
+#define ASL_FWD_LIKE(ref_, expr_) (static_cast<::asl::copy_cref_t<ref_, decltype(expr_)&&>>(expr_))
+
namespace asl
{
diff --git a/asl/base/utility_tests.cpp b/asl/base/utility_tests.cpp
index 4b8e3d1..d959369 100644
--- a/asl/base/utility_tests.cpp
+++ b/asl/base/utility_tests.cpp
@@ -1 +1,80 @@
#include "asl/base/utility.hpp"
+#include "asl/testing/testing.hpp"
+
+template<typename T> static constexpr int identify(const T&) { return 1; }
+template<typename T> static constexpr int identify(const T&&) { return 2; }
+template<typename T> static constexpr int identify(T&) { return 3; }
+template<typename T> static constexpr int identify(T&&) { return 4; }
+
+struct IdentifySelf
+{
+ template<typename Self>
+ constexpr int get(this Self&& self) { return identify(ASL_FWD(self)); }
+};
+
+static int get_const_lref(const IdentifySelf& i) { return ASL_FWD(i).get(); }
+static int get_const_rref(const IdentifySelf&& i) { return ASL_FWD(i).get(); }
+static int get_lref(IdentifySelf& i) { return ASL_FWD(i).get(); }
+static int get_rref(IdentifySelf&& i) { return ASL_FWD(i).get(); }
+
+ASL_TEST(forward)
+{
+ IdentifySelf id;
+ ASL_TEST_EXPECT(get_const_lref(id) == 1);
+ ASL_TEST_EXPECT(get_lref(id) == 3);
+ ASL_TEST_EXPECT(get_const_rref(ASL_MOVE(id)) == 2);
+ ASL_TEST_EXPECT(get_rref(ASL_MOVE(id)) == 4);
+}
+
+ASL_TEST(move)
+{
+ IdentifySelf id;
+ ASL_TEST_EXPECT(id.get() == 3);
+ ASL_TEST_EXPECT(ASL_MOVE(id).get() == 4);
+}
+
+struct Level1
+{
+ IdentifySelf id;
+};
+
+struct Level2
+{
+ Level1 deeper;
+};
+
+struct Level3
+{
+ Level2 deeper;
+};
+
+static int get_const_lref(const Level3& i) { return ASL_FWD(i).deeper.deeper.id.get(); }
+static int get_const_rref(const Level3&& i) { return ASL_FWD(i).deeper.deeper.id.get(); }
+static int get_lref(Level3& i) { return ASL_FWD(i).deeper.deeper.id.get(); }
+static int get_rref(Level3&& i) { return ASL_FWD(i).deeper.deeper.id.get(); }
+
+ASL_TEST(forward2)
+{
+ Level3 id{};
+ ASL_TEST_EXPECT(get_const_lref(id) == 1);
+ ASL_TEST_EXPECT(get_lref(id) == 3);
+ ASL_TEST_EXPECT(get_const_rref(ASL_MOVE(id)) == 2);
+ ASL_TEST_EXPECT(get_rref(ASL_MOVE(id)) == 4);
+}
+
+template<typename T>
+static int test_fwd_like(T&& t)
+{
+ IdentifySelf id;
+ return ASL_FWD_LIKE(decltype(t), id).get();
+}
+
+ASL_TEST(forward_like)
+{
+ int x{};
+ ASL_TEST_EXPECT(test_fwd_like<const int&>(x) == 1);
+ ASL_TEST_EXPECT(test_fwd_like<int&>(x) == 3);
+ ASL_TEST_EXPECT(test_fwd_like<const int&&>(ASL_MOVE(x)) == 2);
+ ASL_TEST_EXPECT(test_fwd_like<int&&>(ASL_MOVE(x)) == 4);
+}
+