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 | /* libbabeltrace2 object pointer */ |
01bf7a3a PP |
74 | using _LibObjPtr = LibObjT *; |
75 | ||
b5f55e9f | 76 | /* This complete borrowed object */ |
0d218157 | 77 | using _ThisBorrowedObject = BorrowedObject<LibObjT>; |
01bf7a3a PP |
78 | |
79 | /* | |
80 | * Builds a borrowed object to wrap the libbabeltrace2 object | |
81 | * pointer `libObjPtr`. | |
82 | * | |
83 | * `libObjPtr` must not be `nullptr`. | |
84 | */ | |
0d218157 | 85 | explicit BorrowedObject(const _LibObjPtr libObjPtr) noexcept : _mLibObjPtr {libObjPtr} |
01bf7a3a PP |
86 | { |
87 | BT_ASSERT(libObjPtr); | |
88 | } | |
89 | ||
5b2d3ebb | 90 | /* Default copy operations */ |
0d218157 PP |
91 | BorrowedObject(const BorrowedObject&) noexcept = default; |
92 | BorrowedObject& operator=(const BorrowedObject&) noexcept = default; | |
5b2d3ebb | 93 | |
01bf7a3a | 94 | /* |
5b2d3ebb | 95 | * Generic "copy" constructor. |
01bf7a3a PP |
96 | * |
97 | * This converting constructor accepts both an instance of | |
0d218157 PP |
98 | * `_ThisBorrowedObject` and an instance (`other`) of |
99 | * `BorrowedObject<ConstLibObjT>`, where `ConstLibObjT` is the | |
100 | * `const` version of `LibObjT`, if applicable. | |
01bf7a3a | 101 | * |
0d218157 | 102 | * This makes it possible for a `BorrowedObject<const bt_something>` |
01bf7a3a | 103 | * instance to be built from an instance of |
0d218157 | 104 | * `BorrowedObject<bt_something>`. C++ forbids the other way around. |
01bf7a3a PP |
105 | */ |
106 | template <typename OtherLibObjT> | |
0d218157 PP |
107 | BorrowedObject(const BorrowedObject<OtherLibObjT>& other) noexcept : |
108 | BorrowedObject {other._mLibObjPtr} | |
01bf7a3a | 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 | |
0d218157 PP |
118 | * `_ThisBorrowedObject` and an instance (`other`) of |
119 | * `BorrowedObject<ConstLibObjT>`, where `ConstLibObjT` is the | |
120 | * `const` version of `LibObjT`, if applicable. | |
01bf7a3a | 121 | * |
0d218157 | 122 | * This makes it possible for a `BorrowedObject<const bt_something>` |
01bf7a3a | 123 | * instance to get assigned an instance of |
0d218157 | 124 | * `BorrowedObject<bt_something>`. C++ forbids the other way around, |
462e8628 PP |
125 | * therefore we use `_EnableIfAssignableT` to show a more relevant |
126 | * context in the compiler error message. | |
01bf7a3a PP |
127 | */ |
128 | template <typename OtherLibObjT> | |
0d218157 | 129 | _ThisBorrowedObject& operator=(const BorrowedObject<OtherLibObjT>& other) noexcept |
01bf7a3a | 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 | /* | |
0d218157 PP |
140 | * Returns a hash of this object, solely based on its raw |
141 | * libbabeltrace2 pointer. | |
feeaa247 FD |
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 | */ | |
0d218157 | 152 | bool isSame(const _ThisBorrowedObject& other) const noexcept |
feeaa247 FD |
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 | 167 | } /* namespace bt2 */ |
01bf7a3a | 168 | |
0d218157 | 169 | #endif /* BABELTRACE_CPP_COMMON_BT2_BORROWED_OBJECT_HPP */ |