-
Notifications
You must be signed in to change notification settings - Fork 6
/
cached.hpp
80 lines (67 loc) · 2.13 KB
/
cached.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
#pragma once
#include <stdx/compiler.hpp>
#include <stdx/functional.hpp>
#include <stdx/type_traits.hpp>
#include <optional>
#include <type_traits>
#include <utility>
namespace stdx {
inline namespace v1 {
template <typename F> class cached : with_result_of<F> {
using lazy_t = with_result_of<F>;
public:
using value_type = stdx::remove_cvref_t<std::invoke_result_t<F>>;
constexpr explicit cached(F const &f) : lazy_t{f} {}
constexpr explicit cached(F &&f) : lazy_t{std::move(f)} {}
auto has_value() const noexcept -> bool { return opt.has_value(); }
explicit operator bool() const noexcept { return opt.has_value(); }
explicit operator bool() noexcept { return opt.has_value(); }
auto value() & LIFETIMEBOUND -> value_type & {
populate();
return *opt;
}
auto value() const & LIFETIMEBOUND -> value_type const & {
populate();
return *opt;
}
auto value() && LIFETIMEBOUND -> value_type && {
populate();
return *std::move(opt);
}
auto value() const && LIFETIMEBOUND -> value_type const && {
populate();
return *std::move(opt);
}
auto operator->() const LIFETIMEBOUND->value_type const * {
populate();
return opt.operator->();
}
auto operator->() LIFETIMEBOUND->value_type * {
populate();
return opt.operator->();
}
auto operator*() const & LIFETIMEBOUND->decltype(auto) { return value(); }
auto operator*() & LIFETIMEBOUND->decltype(auto) { return value(); }
auto operator*() const && LIFETIMEBOUND->decltype(auto) {
return std::move(*this).value();
}
auto operator*() && LIFETIMEBOUND->decltype(auto) {
return std::move(*this).value();
}
auto reset() { opt.reset(); }
auto refresh() {
opt.reset();
populate();
}
private:
auto populate() const {
if (not opt.has_value()) {
opt.emplace(static_cast<lazy_t>(*this));
}
}
mutable std::optional<value_type> opt{};
};
template <typename C>
using cached_value_t = typename stdx::remove_cvref_t<C>::value_type;
} // namespace v1
} // namespace stdx