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. | |
01bf7a3a PP |
28 | */ |
29 | template <typename LibObjT> | |
0d218157 | 30 | class BorrowedObject |
01bf7a3a PP |
31 | { |
32 | static_assert(!std::is_pointer<LibObjT>::value, "`LibObjT` must not be a pointer"); | |
33 | ||
34 | /* | |
0d218157 | 35 | * This makes it possible for a `BorrowedObject<const bt_something>` |
01bf7a3a | 36 | * instance to get assigned an instance of |
0d218157 PP |
37 | * `BorrowedObject<bt_something>` ("copy" constructor and |
38 | * "assignment" operator). | |
01bf7a3a PP |
39 | * |
40 | * C++ forbids the other way around. | |
41 | */ | |
96643d28 | 42 | template <typename> |
0d218157 | 43 | friend class BorrowedObject; |
01bf7a3a | 44 | |
462e8628 PP |
45 | private: |
46 | /* | |
47 | * Provides `val` which indicates whether or not you can assign this | |
48 | * object from a borrowed object of type `OtherLibObjT`. | |
49 | */ | |
50 | template <typename OtherLibObjT> | |
51 | struct _AssignableFromConst final | |
52 | { | |
53 | /* | |
54 | * If `LibObjT` is const (for example, `const bt_value`), then | |
55 | * you may always assign from its non-const equivalent (for | |
56 | * example, `bt_value`). In C (correct): | |
57 | * | |
58 | * bt_value * const meow = bt_value_bool_create_init(BT_TRUE); | |
59 | * const bt_value * const mix = meow; | |
60 | * | |
61 | * If `LibObjT` is non-const, then you may not assign from its | |
62 | * const equivalent. In C (not correct): | |
63 | * | |
64 | * const bt_value * const meow = | |
65 | * bt_value_array_borrow_element_by_index_const(some_val, 17); | |
66 | * bt_value * const mix = meow; | |
67 | */ | |
68 | static constexpr bool val = | |
69 | std::is_const<LibObjT>::value || !std::is_const<OtherLibObjT>::value; | |
70 | }; | |
71 | ||
01bf7a3a | 72 | protected: |
b5f55e9f | 73 | /* This complete borrowed object */ |
0d218157 | 74 | using _ThisBorrowedObject = BorrowedObject<LibObjT>; |
01bf7a3a | 75 | |
d246c457 PP |
76 | public: |
77 | /* libbabeltrace2 object */ | |
78 | using LibObj = LibObjT; | |
79 | ||
80 | /* libbabeltrace2 object pointer */ | |
81 | using LibObjPtr = LibObjT *; | |
82 | ||
83 | protected: | |
01bf7a3a PP |
84 | /* |
85 | * Builds a borrowed object to wrap the libbabeltrace2 object | |
86 | * pointer `libObjPtr`. | |
87 | * | |
88 | * `libObjPtr` must not be `nullptr`. | |
89 | */ | |
d246c457 | 90 | explicit BorrowedObject(const LibObjPtr libObjPtr) noexcept : _mLibObjPtr {libObjPtr} |
01bf7a3a | 91 | { |
bec20c88 | 92 | BT_ASSERT_DBG(libObjPtr); |
01bf7a3a PP |
93 | } |
94 | ||
95 | /* | |
5b2d3ebb | 96 | * Generic "copy" constructor. |
01bf7a3a PP |
97 | * |
98 | * This converting constructor accepts both an instance of | |
0d218157 PP |
99 | * `_ThisBorrowedObject` and an instance (`other`) of |
100 | * `BorrowedObject<ConstLibObjT>`, where `ConstLibObjT` is the | |
101 | * `const` version of `LibObjT`, if applicable. | |
01bf7a3a | 102 | * |
0d218157 | 103 | * This makes it possible for a `BorrowedObject<const bt_something>` |
01bf7a3a | 104 | * instance to be built from an instance of |
0d218157 | 105 | * `BorrowedObject<bt_something>`. C++ forbids the other way around. |
01bf7a3a PP |
106 | */ |
107 | template <typename OtherLibObjT> | |
0d218157 PP |
108 | BorrowedObject(const BorrowedObject<OtherLibObjT>& other) noexcept : |
109 | BorrowedObject {other._mLibObjPtr} | |
01bf7a3a | 110 | { |
462e8628 PP |
111 | static_assert(_AssignableFromConst<OtherLibObjT>::val, |
112 | "Don't assign a non-const wrapper from a const wrapper."); | |
01bf7a3a PP |
113 | } |
114 | ||
115 | /* | |
5b2d3ebb | 116 | * Generic "assignment" operator. |
01bf7a3a PP |
117 | * |
118 | * This operator accepts both an instance of | |
0d218157 PP |
119 | * `_ThisBorrowedObject` and an instance (`other`) of |
120 | * `BorrowedObject<ConstLibObjT>`, where `ConstLibObjT` is the | |
121 | * `const` version of `LibObjT`, if applicable. | |
01bf7a3a | 122 | * |
0d218157 | 123 | * This makes it possible for a `BorrowedObject<const bt_something>` |
01bf7a3a | 124 | * instance to get assigned an instance of |
0d218157 | 125 | * `BorrowedObject<bt_something>`. C++ forbids the other way around, |
462e8628 PP |
126 | * therefore we use `_EnableIfAssignableT` to show a more relevant |
127 | * context in the compiler error message. | |
01bf7a3a PP |
128 | */ |
129 | template <typename OtherLibObjT> | |
ac30a470 | 130 | _ThisBorrowedObject operator=(const BorrowedObject<OtherLibObjT>& other) noexcept |
01bf7a3a | 131 | { |
462e8628 PP |
132 | static_assert(_AssignableFromConst<OtherLibObjT>::val, |
133 | "Don't assign a non-const wrapper from a const wrapper."); | |
134 | ||
01bf7a3a PP |
135 | _mLibObjPtr = other._mLibObjPtr; |
136 | return *this; | |
137 | } | |
138 | ||
feeaa247 FD |
139 | public: |
140 | /* | |
0d218157 PP |
141 | * Returns a hash of this object, solely based on its raw |
142 | * libbabeltrace2 pointer. | |
feeaa247 FD |
143 | */ |
144 | std::size_t hash() const noexcept | |
145 | { | |
d246c457 | 146 | return std::hash<LibObjPtr> {}(_mLibObjPtr); |
feeaa247 FD |
147 | } |
148 | ||
149 | /* | |
150 | * Returns whether or not this object is the exact same as `other`, | |
151 | * solely based on the raw libbabeltrace2 pointers. | |
152 | */ | |
0d218157 | 153 | bool isSame(const _ThisBorrowedObject& other) const noexcept |
feeaa247 FD |
154 | { |
155 | return _mLibObjPtr == other._mLibObjPtr; | |
156 | } | |
157 | ||
b5f55e9f | 158 | /* Wrapped libbabeltrace2 object pointer */ |
d246c457 | 159 | LibObjPtr libObjPtr() const noexcept |
01bf7a3a PP |
160 | { |
161 | return _mLibObjPtr; | |
162 | } | |
163 | ||
164 | private: | |
d246c457 | 165 | LibObjPtr _mLibObjPtr; |
01bf7a3a PP |
166 | }; |
167 | ||
b5f55e9f | 168 | } /* namespace bt2 */ |
01bf7a3a | 169 | |
0d218157 | 170 | #endif /* BABELTRACE_CPP_COMMON_BT2_BORROWED_OBJECT_HPP */ |