open62541pp 0.16.0
C++ wrapper of open62541
Loading...
Searching...
No Matches
wrapper.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <type_traits>
4
5namespace opcua {
6
7/**
8 * @defgroup Wrapper Wrapper classes
9 *
10 * All wrapper classes inherit from Wrapper (and optionally from TypeWrapper).
11 * Native open62541 objects can be accessed using the Wrapper::handle() method.
12 *
13 * Wrapper types are pointer-interconvertible to the wrapped native type and vice versa:
14 * - Use asWrapper(NativeType*) to cast native object pointers to wrapper object pointers.
15 * - Use asWrapper(NativeType&) to cast native object references to wrapper object references.
16 * - Use asNative(WrapperType*) to cast wrapper object pointers to native object pointers.
17 * - Use asNative(WrapperType&) to cast wrapper object references to native object references.
18 *
19 * According to the standard:
20 * > Two objects `a` and `b` are pointer-interconvertible if:
21 * > One is a standard-layout class object [wrapper] and the other is the first non-static data
22 * > member of that object [wrapped native type].
23 * Derived classes must fulfill the requirements of standard-layout types to be convertible.
24 * @see https://en.cppreference.com/w/cpp/language/static_cast#pointer-interconvertible
25 */
26
27/**
28 * Template base class to wrap native objects.
29 * @ingroup Wrapper
30 */
31template <typename T>
32class Wrapper {
33public:
34 using NativeType = T;
35
36 constexpr Wrapper() = default;
37
38 constexpr explicit Wrapper(const T& native)
39 : native_(native) {}
40
41 constexpr explicit Wrapper(T&& native) noexcept
42 : native_(std::move(native)) {}
43
44 /// Implicit conversion to native object.
45 constexpr operator T&() noexcept { // NOLINT(hicpp-explicit-conversions)
46 return native_;
47 }
48
49 /// Implicit conversion to native object.
50 constexpr operator const T&() const noexcept { // NOLINT(hicpp-explicit-conversions)
51 return native_;
52 }
53
54 /// Member access to native object.
55 constexpr T* operator->() noexcept {
56 return &native_;
57 }
58
59 /// Member access to native object.
60 constexpr const T* operator->() const noexcept {
61 return &native_;
62 }
63
64 /// Return pointer to native object.
65 constexpr T* handle() noexcept {
66 return &native_;
67 }
68
69 /// Return pointer to native object.
70 constexpr const T* handle() const noexcept {
71 return &native_;
72 }
73
74protected:
75 constexpr const T& native() const noexcept {
76 return native_;
77 }
78
79 constexpr T& native() noexcept {
80 return native_;
81 }
82
83private:
84 T native_{};
85};
86
87/* -------------------------------------------- Trait ------------------------------------------- */
88
89namespace detail {
90
91template <typename T>
92struct IsWrapper {
93 // https://stackoverflow.com/a/51910887
94 template <typename U>
95 static std::true_type check(const Wrapper<U>&);
96 static std::false_type check(...);
97
98 using type = decltype(check(std::declval<T&>()));
99 static constexpr bool value = type::value;
100};
101
102template <typename T>
104
105} // namespace detail
106
107/* ------------------------------ Cast native type to wrapper type ------------------------------ */
108
109namespace detail {
110
111template <typename WrapperType>
113 static_assert(isWrapper<WrapperType>);
114 static_assert(std::is_standard_layout_v<WrapperType>);
115
116 using NativeType = typename WrapperType::NativeType;
117
118 // NOLINTBEGIN(bugprone-casting-through-void)
119 static constexpr WrapperType* asWrapper(NativeType* native) noexcept {
120 return static_cast<WrapperType*>(static_cast<void*>(native));
121 }
122
123 static constexpr const WrapperType* asWrapper(const NativeType* native) noexcept {
124 return static_cast<const WrapperType*>(static_cast<const void*>(native));
125 }
126
127 static constexpr WrapperType& asWrapper(NativeType& native) noexcept {
128 return *asWrapper(&native);
129 }
130
131 static constexpr const WrapperType& asWrapper(const NativeType& native) noexcept {
132 return *asWrapper(&native);
133 }
134
135 static constexpr NativeType* asNative(WrapperType* wrapper) noexcept {
136 return static_cast<NativeType*>(static_cast<void*>(wrapper));
137 }
138
139 static constexpr const NativeType* asNative(const WrapperType* wrapper) noexcept {
140 return static_cast<const NativeType*>(static_cast<const void*>(wrapper));
141 }
142
143 static constexpr NativeType& asNative(WrapperType& wrapper) noexcept {
144 return *asNative(&wrapper);
145 }
146
147 static constexpr const NativeType& asNative(const WrapperType& wrapper) noexcept {
148 return *asNative(&wrapper);
149 }
150
151 // NOLINTEND(bugprone-casting-through-void)
152};
153
154} // namespace detail
155
156/**
157 * @ingroup Wrapper
158 * @{
159 */
160
161/// Cast native object pointers to Wrapper object pointers.
162/// This is especially helpful to avoid copies in getter methods of composed types.
163/// @see https://github.com/open62541pp/open62541pp/issues/30
164template <typename WrapperType, typename NativeType = typename WrapperType::NativeType>
165constexpr WrapperType* asWrapper(NativeType* native) noexcept {
167}
168
169/// @copydoc asWrapper(NativeType*)
170template <typename WrapperType, typename NativeType = typename WrapperType::NativeType>
171constexpr const WrapperType* asWrapper(const NativeType* native) noexcept {
173}
174
175/// Cast native object references to Wrapper object references.
176/// @copydetails asWrapper(NativeType*)
177template <typename WrapperType, typename NativeType = typename WrapperType::NativeType>
178constexpr WrapperType& asWrapper(NativeType& native) noexcept {
180}
181
182/// @copydoc asWrapper(NativeType&)
183template <typename WrapperType, typename NativeType = typename WrapperType::NativeType>
184constexpr const WrapperType& asWrapper(const NativeType& native) noexcept {
186}
187
188/// Cast Wrapper object pointers to native object pointers.
189/// @copydoc detail::WrapperConversion
190template <typename WrapperType, typename NativeType = typename WrapperType::NativeType>
191constexpr NativeType* asNative(WrapperType* wrapper) noexcept {
193}
194
195/// @copydoc asNative(WrapperType*)
196template <typename WrapperType, typename NativeType = typename WrapperType::NativeType>
197constexpr const NativeType* asNative(const WrapperType* wrapper) noexcept {
199}
200
201/// Cast Wrapper object references to native object references.
202/// @copydetails asNative(WrapperType*)
203template <typename WrapperType, typename NativeType = typename WrapperType::NativeType>
204constexpr NativeType& asNative(WrapperType& wrapper) noexcept {
206}
207
208/// @copydoc asNative(WrapperType&)
209template <typename WrapperType, typename NativeType = typename WrapperType::NativeType>
210constexpr const NativeType& asNative(const WrapperType& wrapper) noexcept {
212}
213
214/**
215 * @}
216 */
217
218} // namespace opcua
Template base class to wrap native objects.
Definition wrapper.hpp:32
constexpr const T * operator->() const noexcept
Member access to native object.
Definition wrapper.hpp:60
constexpr T * operator->() noexcept
Member access to native object.
Definition wrapper.hpp:55
constexpr const T & native() const noexcept
Definition wrapper.hpp:75
constexpr const T * handle() const noexcept
Return pointer to native object.
Definition wrapper.hpp:70
constexpr T & native() noexcept
Definition wrapper.hpp:79
constexpr T * handle() noexcept
Return pointer to native object.
Definition wrapper.hpp:65
constexpr Wrapper(T &&native) noexcept
Definition wrapper.hpp:41
constexpr Wrapper(const T &native)
Definition wrapper.hpp:38
constexpr Wrapper()=default
constexpr NativeType * asNative(WrapperType *wrapper) noexcept
Cast Wrapper object pointers to native object pointers.
Definition wrapper.hpp:191
constexpr bool isWrapper
Definition wrapper.hpp:103
Client * asWrapper(UA_Client *client) noexcept
Convert native UA_Client pointer to its wrapper instance.
static constexpr bool value
Definition wrapper.hpp:99
static std::true_type check(const Wrapper< U > &)
static std::false_type check(...)
decltype(check(std::declval< T & >())) type
Definition wrapper.hpp:98
static constexpr const WrapperType * asWrapper(const NativeType *native) noexcept
Definition wrapper.hpp:123
static constexpr NativeType * asNative(WrapperType *wrapper) noexcept
Definition wrapper.hpp:135
static constexpr const NativeType * asNative(const WrapperType *wrapper) noexcept
Definition wrapper.hpp:139
static constexpr WrapperType * asWrapper(NativeType *native) noexcept
Definition wrapper.hpp:119
static constexpr const WrapperType & asWrapper(const NativeType &native) noexcept
Definition wrapper.hpp:131
static constexpr NativeType & asNative(WrapperType &wrapper) noexcept
Definition wrapper.hpp:143
static constexpr WrapperType & asWrapper(NativeType &native) noexcept
Definition wrapper.hpp:127
typename WrapperType::NativeType NativeType
Definition wrapper.hpp:116
static constexpr const NativeType & asNative(const WrapperType &wrapper) noexcept
Definition wrapper.hpp:147