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