Commit | Line | Data |
---|---|---|
01bf7a3a PP |
1 | /* |
2 | * Copyright 2019-2020 (c) Philippe Proulx <pproulx@efficios.com> | |
3 | * | |
4 | * SPDX-License-Identifier: MIT | |
5 | */ | |
6 | ||
0d218157 PP |
7 | #ifndef BABELTRACE_CPP_COMMON_BT2_BORROWED_OBJECT_HPP |
8 | #define BABELTRACE_CPP_COMMON_BT2_BORROWED_OBJECT_HPP | |
01bf7a3a | 9 | |
feeaa247 | 10 | #include <functional> |
01bf7a3a PP |
11 | #include <type_traits> |
12 | ||
13 | #include "common/assert.h" | |
14 | ||
15 | namespace bt2 { | |
01bf7a3a | 16 | |
01bf7a3a PP |
17 | /* |
18 | * An instance of this class wraps a pointer to a libbabeltrace2 object | |
19 | * of type `LibObjT` without managing any reference counting. | |
20 | * | |
21 | * This is an abstract base class for any libbabeltrace2 object wrapper. | |
22 | * | |
23 | * `LibObjT` is the direct libbabeltrace2 object type, for example | |
24 | * `bt_stream_class` or `const bt_value`. | |
25 | * | |
75aa724c PP |
26 | * The user of a borrowed object, including methods of a derived class, |
27 | * can call libObjPtr() to access the libbabeltrace2 object pointer. | |
db5a1938 PP |
28 | * |
29 | * You may only build a borrowed object with a pointer which isn't | |
30 | * `nullptr`. See `bt2::OptionalBorrowedObject` for an optional version. | |
01bf7a3a PP |
31 | */ |
32 | template <typename LibObjT> | |
0d218157 | 33 | class BorrowedObject |
01bf7a3a PP |
34 | { |
35 | static_assert(!std::is_pointer<LibObjT>::value, "`LibObjT` must not be a pointer"); | |
36 | ||
37 | /* | |
0d218157 | 38 | * This makes it possible for a `BorrowedObject<const bt_something>` |
01bf7a3a | 39 | * instance to get assigned an instance of |
0d218157 PP |
40 | * `BorrowedObject<bt_something>` ("copy" constructor and |
41 | * "assignment" operator). | |
01bf7a3a PP |
42 | * |
43 | * C++ forbids the other way around. | |
44 | */ | |
96643d28 | 45 | template <typename> |
0d218157 | 46 | friend class BorrowedObject; |
01bf7a3a | 47 | |
462e8628 PP |
48 | private: |
49 | /* | |
50 | * Provides `val` which indicates whether or not you can assign this | |
51 | * object from a borrowed object of type `OtherLibObjT`. | |
52 | */ | |
53 | template <typename OtherLibObjT> | |
54 | struct _AssignableFromConst final | |
55 | { | |
56 | /* | |
57 | * If `LibObjT` is const (for example, `const bt_value`), then | |
58 | * you may always assign from its non-const equivalent (for | |
59 | * example, `bt_value`). In C (correct): | |
60 | * | |
61 | * bt_value * const meow = bt_value_bool_create_init(BT_TRUE); | |
62 | * const bt_value * const mix = meow; | |
63 | * | |
64 | * If `LibObjT` is non-const, then you may not assign from its | |
65 | * const equivalent. In C (not correct): | |
66 | * | |
67 | * const bt_value * const meow = | |
68 | * bt_value_array_borrow_element_by_index_const(some_val, 17); | |
69 | * bt_value * const mix = meow; | |
70 | */ | |
71 | static constexpr bool val = | |
72 | std::is_const<LibObjT>::value || !std::is_const<OtherLibObjT>::value; | |
73 | }; | |
74 | ||
01bf7a3a | 75 | protected: |
b5f55e9f | 76 | /* This complete borrowed object */ |
0d218157 | 77 | using _ThisBorrowedObject = BorrowedObject<LibObjT>; |
01bf7a3a | 78 | |
d246c457 PP |
79 | public: |
80 | /* libbabeltrace2 object */ | |
81 | using LibObj = LibObjT; | |
82 | ||
83 | /* libbabeltrace2 object pointer */ | |
84 | using LibObjPtr = LibObjT *; | |
85 | ||
86 | protected: | |
01bf7a3a PP |
87 | /* |
88 | * Builds a borrowed object to wrap the libbabeltrace2 object | |
89 | * pointer `libObjPtr`. | |
90 | * | |
91 | * `libObjPtr` must not be `nullptr`. | |
92 | */ | |
d246c457 | 93 | explicit BorrowedObject(const LibObjPtr libObjPtr) noexcept : _mLibObjPtr {libObjPtr} |
01bf7a3a | 94 | { |
bec20c88 | 95 | BT_ASSERT_DBG(libObjPtr); |
01bf7a3a PP |
96 | } |
97 | ||
98 | /* | |
5b2d3ebb | 99 | * Generic "copy" constructor. |
01bf7a3a PP |
100 | * |
101 | * This converting constructor accepts both an instance of | |
0d218157 PP |
102 | * `_ThisBorrowedObject` and an instance (`other`) of |
103 | * `BorrowedObject<ConstLibObjT>`, where `ConstLibObjT` is the | |
104 | * `const` version of `LibObjT`, if applicable. | |
01bf7a3a | 105 | * |
0d218157 | 106 | * This makes it possible for a `BorrowedObject<const bt_something>` |
01bf7a3a | 107 | * instance to be built from an instance of |
0d218157 | 108 | * `BorrowedObject<bt_something>`. C++ forbids the other way around. |
01bf7a3a PP |
109 | */ |
110 | template <typename OtherLibObjT> | |
0d218157 PP |
111 | BorrowedObject(const BorrowedObject<OtherLibObjT>& other) noexcept : |
112 | BorrowedObject {other._mLibObjPtr} | |
01bf7a3a | 113 | { |
462e8628 PP |
114 | static_assert(_AssignableFromConst<OtherLibObjT>::val, |
115 | "Don't assign a non-const wrapper from a const wrapper."); | |
01bf7a3a PP |
116 | } |
117 | ||
118 | /* | |
5b2d3ebb | 119 | * Generic "assignment" operator. |
01bf7a3a PP |
120 | * |
121 | * This operator accepts both an instance of | |
0d218157 PP |
122 | * `_ThisBorrowedObject` and an instance (`other`) of |
123 | * `BorrowedObject<ConstLibObjT>`, where `ConstLibObjT` is the | |
124 | * `const` version of `LibObjT`, if applicable. | |
01bf7a3a | 125 | * |
0d218157 | 126 | * This makes it possible for a `BorrowedObject<const bt_something>` |
01bf7a3a | 127 | * instance to get assigned an instance of |
0d218157 | 128 | * `BorrowedObject<bt_something>`. C++ forbids the other way around, |
462e8628 PP |
129 | * therefore we use `_EnableIfAssignableT` to show a more relevant |
130 | * context in the compiler error message. | |
01bf7a3a PP |
131 | */ |
132 | template <typename OtherLibObjT> | |
ac30a470 | 133 | _ThisBorrowedObject operator=(const BorrowedObject<OtherLibObjT>& other) noexcept |
01bf7a3a | 134 | { |
462e8628 PP |
135 | static_assert(_AssignableFromConst<OtherLibObjT>::val, |
136 | "Don't assign a non-const wrapper from a const wrapper."); | |
137 | ||
01bf7a3a PP |
138 | _mLibObjPtr = other._mLibObjPtr; |
139 | return *this; | |
140 | } | |
141 | ||
feeaa247 FD |
142 | public: |
143 | /* | |
0d218157 PP |
144 | * Returns a hash of this object, solely based on its raw |
145 | * libbabeltrace2 pointer. | |
feeaa247 FD |
146 | */ |
147 | std::size_t hash() const noexcept | |
148 | { | |
d246c457 | 149 | return std::hash<LibObjPtr> {}(_mLibObjPtr); |
feeaa247 FD |
150 | } |
151 | ||
152 | /* | |
153 | * Returns whether or not this object is the exact same as `other`, | |
154 | * solely based on the raw libbabeltrace2 pointers. | |
155 | */ | |
0d218157 | 156 | bool isSame(const _ThisBorrowedObject& other) const noexcept |
feeaa247 FD |
157 | { |
158 | return _mLibObjPtr == other._mLibObjPtr; | |
159 | } | |
160 | ||
b5f55e9f | 161 | /* Wrapped libbabeltrace2 object pointer */ |
d246c457 | 162 | LibObjPtr libObjPtr() const noexcept |
01bf7a3a PP |
163 | { |
164 | return _mLibObjPtr; | |
165 | } | |
166 | ||
167 | private: | |
d246c457 | 168 | LibObjPtr _mLibObjPtr; |
01bf7a3a PP |
169 | }; |
170 | ||
b5f55e9f | 171 | } /* namespace bt2 */ |
01bf7a3a | 172 | |
0d218157 | 173 | #endif /* BABELTRACE_CPP_COMMON_BT2_BORROWED_OBJECT_HPP */ |