Skip to content

Commit 201b2f1

Browse files
committed
ref partial
1 parent ba59e81 commit 201b2f1

File tree

2 files changed

+57
-7
lines changed

2 files changed

+57
-7
lines changed

include/libfork/ev.hpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,4 +75,20 @@ class ev<T> : detail::immovable<ev<T>> {
7575
T m_value;
7676
};
7777

78+
/**
79+
* @brief A specialisation of `ev` for reference types.
80+
*/
81+
template <typename T>
82+
requires std::is_reference_v<T>
83+
class ev<T> {
84+
public:
85+
template <typename Self>
86+
[[nodiscard]] constexpr auto operator*(this Self &&self) noexcept -> auto && {
87+
return std::forward_like<Self>(*self.m_ptr);
88+
}
89+
90+
private:
91+
std::add_pointer_t<std::remove_reference_t<T>> m_ptr;
92+
};
93+
7894
} // namespace lf

test/src/test_ev.cpp

Lines changed: 41 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,57 @@
11

2-
#include <string>
2+
#include <type_traits>
33

44
#include <catch2/catch_template_test_macros.hpp>
55
#include <catch2/catch_test_macros.hpp>
66

77
#include "libfork/ev.hpp"
88

9-
TEMPLATE_TEST_CASE("Eventually operator *", "[ev]", int, std::string) {
9+
namespace {
10+
11+
template <typename T>
12+
concept good_deref = requires (lf::ev<T> val, T ref) {
13+
{ *val } -> std::same_as<decltype((ref))>;
14+
};
15+
16+
template <typename T>
17+
struct add_const : std::type_identity<T const> {};
18+
19+
template <typename T>
20+
struct add_const<T &> : std::type_identity<T const &> {};
21+
22+
template <typename T>
23+
struct add_const<T &&> : std::type_identity<T const &&> {};
24+
25+
template <typename T>
26+
concept good_decref = requires (lf::ev<T> const val, typename add_const<T>::type ref) {
27+
{ *val } -> std::same_as<decltype((ref))>;
28+
};
29+
30+
struct nt {
31+
nt() {}
32+
};
33+
34+
static_assert(!lf::trivial_return<nt>);
35+
36+
} // namespace
37+
38+
TEMPLATE_TEST_CASE("Ev operator *", "[ev]", nt, int, int &, int &&, int const &, int const &&) {
39+
40+
using U = std::remove_reference_t<TestType>;
41+
42+
static_assert(good_deref<TestType>);
43+
static_assert(good_decref<TestType>);
1044

1145
lf::ev<TestType> val{};
12-
static_assert(std::same_as<decltype(*val), TestType &>);
13-
static_assert(std::same_as<decltype(*std::move(val)), TestType &&>);
46+
static_assert(std::same_as<decltype(*val), U &>);
47+
static_assert(std::same_as<decltype(*std::move(val)), U &&>);
1448

1549
lf::ev<TestType> const cval{};
16-
static_assert(std::same_as<decltype(*cval), TestType const &>);
17-
static_assert(std::same_as<decltype(*std::move(cval)), TestType const &&>);
50+
static_assert(std::same_as<decltype(*cval), U const &>);
51+
static_assert(std::same_as<decltype(*std::move(cval)), U const &&>);
1852
}
1953

20-
TEMPLATE_TEST_CASE("Eventually operator ->", "[ev]", int, std::string) {
54+
TEMPLATE_TEST_CASE("Eventually operator ->", "[ev]", nt, int) {
2155

2256
lf::ev<TestType> val{};
2357
static_assert(std::same_as<decltype(val.operator->()), TestType *>);

0 commit comments

Comments
 (0)