Nix 2.93.3
Lix: A modern, delicious implementation of the Nix package manager; unstable internal interfaces
Loading...
Searching...
No Matches
box_ptr.hh
Go to the documentation of this file.
1#pragma once
3
4#include <concepts>
5#include <memory>
6#include <stdexcept>
7#include <type_traits>
8#include <assert.h>
9
10namespace nix {
11
13template<typename T>
14// FIXME: add custom deleter support
15class box_ptr
16{
17 std::unique_ptr<T> inner;
18
19 template<typename T2>
20 friend class box_ptr;
21
22 explicit box_ptr(std::unique_ptr<T> p)
23 : inner(std::move(p))
24 {
25 assert(inner != nullptr);
26 }
27
28public:
29 using pointer = typename std::unique_ptr<T>::pointer;
30
31 inline typename std::add_lvalue_reference<T>::type operator*() const noexcept
32 {
33 return *inner.get();
34 }
35
36 inline pointer operator->() const noexcept
37 {
38 return inner.get();
39 }
40
41 inline pointer get() const noexcept
42 {
43 return inner.get();
44 }
45
49 static inline box_ptr<T> unsafeFromNonnull(std::unique_ptr<T> p)
50 {
51 return box_ptr(std::move(p));
52 }
53
54 inline box_ptr<T> & operator=(box_ptr<T> && other) noexcept = default;
55
56 // No copy for you.
57 box_ptr<T> & operator=(const box_ptr<T> &) = delete;
58
59 // XXX: we have to set the other's insides to nullptr, since we cannot
60 // put a garbage object there, and we don't have any compiler
61 // enforcement to not touch moved-from values. sighh.
62 box_ptr(box_ptr<T> && other) = default;
63
65 template<typename Other>
66 // n.b. the requirements here are the same as libstdc++ unique_ptr's checks but with concepts
67 requires std::convertible_to<typename box_ptr<Other>::pointer, pointer> &&(!std::is_array_v<Other>)
68 box_ptr(box_ptr<Other> && other) noexcept
69 : inner(std::move(other.inner))
70 {
71 other.inner = nullptr;
72 }
73
74 box_ptr(box_ptr<T> & other) = delete;
75
76 std::unique_ptr<T> take() &&
77 {
78 return std::move(inner);
79 }
80};
81
82template<typename T>
83requires std::equality_comparable<T>
84bool operator==(box_ptr<T> const & x, box_ptr<T> const & y)
85{
86 // Although there could be an optimization here that compares x == y, this
87 // is unsound for floats with NaN, or anything else that violates
88 // reflexivity.
89 return *x == *y;
90}
91
92template<typename T>
93requires std::equality_comparable<T>
94bool operator!=(box_ptr<T> const & x, box_ptr<T> const & y)
95{
96 return *x != *y;
97}
98
99#define MAKE_COMPARISON(OP) \
100 template<typename T> \
101 requires std::totally_ordered<T> \
102 bool operator OP(box_ptr<T> const & x, box_ptr<T> const & y) \
103 { \
104 return *x OP * y; \
105 }
106
107MAKE_COMPARISON(<);
108MAKE_COMPARISON(>);
109MAKE_COMPARISON(>=);
110MAKE_COMPARISON(<=);
111
112#undef MAKE_COMPARISON
113
114template<typename T>
115requires std::three_way_comparable<T> std::compare_three_way_result_t<T, T>
116operator<=>(box_ptr<T> const & x, box_ptr<T> const & y)
117{
118 return *x <=> *y;
119}
120
121template<typename T, typename... Args>
122inline box_ptr<T> make_box_ptr(Args &&... args)
123{
124 return box_ptr<T>::unsafeFromNonnull(std::make_unique<T>(std::forward<Args>(args)...));
125}
126};
Definition args.hh:31
Definition box_ptr.hh:16
static box_ptr< T > unsafeFromNonnull(std::unique_ptr< T > p)
Definition box_ptr.hh:49
box_ptr(box_ptr< Other > &&other) noexcept
Definition box_ptr.hh:68