open62541pp 0.15.0
C++ wrapper of open62541
Loading...
Searching...
No Matches
typewrapper.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <type_traits>
4#include <utility> // exchange, swap
5
6#include "open62541pp/common.hpp" // TypeIndex
10
11namespace opcua {
12
13/**
14 * Template base class to wrap `UA_*` type objects.
15 *
16 * Zero cost abstraction to wrap the C API objects and delete them on destruction. The derived
17 * classes should implement specific constructors to convert from other data types.
18 *
19 * @warning No virtual constructor defined, don't implement a destructor in the derived classes.
20 * @ingroup Wrapper
21 */
22template <typename T, TypeIndex typeIndex>
23class TypeWrapper : public Wrapper<T> {
24public:
25 static_assert(typeIndex < UA_TYPES_COUNT);
26
27 constexpr TypeWrapper() = default;
28
29 /// Constructor with native object (deep copy).
30 explicit constexpr TypeWrapper(const T& native)
31 : Wrapper<T>(detail::copy(native, UA_TYPES[typeIndex])) {}
32
33 /// Constructor with native object (move rvalue).
34 constexpr TypeWrapper(T&& native) noexcept // NOLINT
35 : Wrapper<T>(std::exchange(native, {})) {}
36
38 clear();
39 };
40
41 /// Copy constructor (deep copy).
42 constexpr TypeWrapper(const TypeWrapper& other)
43 : Wrapper<T>(detail::copy(other.native(), UA_TYPES[typeIndex])) {}
44
45 /// Move constructor.
46 constexpr TypeWrapper(TypeWrapper&& other) noexcept
47 : Wrapper<T>(std::exchange(other.native(), {})) {}
48
49 /// Copy assignment (deep copy).
50 constexpr TypeWrapper& operator=(const TypeWrapper& other) {
51 if (this != &other) {
52 clear();
53 this->native() = detail::copy(other.native(), UA_TYPES[typeIndex]);
54 }
55 return *this;
56 }
57
58 /// Copy assignment with native object (deep copy).
59 constexpr TypeWrapper& operator=(const T& native) {
60 if (&this->native() != &native) {
61 clear();
62 this->native() = detail::copy(native, UA_TYPES[typeIndex]);
63 }
64 return *this;
65 }
66
67 /// Move assignment.
68 constexpr TypeWrapper& operator=(TypeWrapper&& other) noexcept {
69 if (this != &other) {
70 clear();
71 this->native() = std::exchange(other.native(), {});
72 }
73 return *this;
74 }
75
76 /// Move assignment with native object.
77 constexpr TypeWrapper& operator=(T&& native) noexcept { // NOLINT
78 if (&this->native() != &native) {
79 clear();
80 this->native() = std::exchange(native, {});
81 }
82 return *this;
83 }
84
85 /// Swap with wrapper object.
86 constexpr void swap(TypeWrapper& other) noexcept {
87 static_assert(std::is_nothrow_swappable_v<T>);
88 std::swap(this->native(), other.native());
89 }
90
91 /// Swap with native object.
92 constexpr void swap(T& native) noexcept {
93 static_assert(std::is_nothrow_swappable_v<T>);
94 std::swap(this->native(), native);
95 }
96
97 /// Get type as type index of the ::UA_TYPES array.
98 static constexpr TypeIndex getTypeIndex() {
99 return typeIndex;
100 }
101
102protected:
103 constexpr void clear() noexcept {
104 detail::clear(this->native(), UA_TYPES[typeIndex]);
105 }
106};
107
108/* -------------------------------------------- Trait ------------------------------------------- */
109
110namespace detail {
111
112template <typename T>
114 // https://stackoverflow.com/a/51910887
115 template <typename U, TypeIndex typeIndex>
116 static std::true_type check(const TypeWrapper<U, typeIndex>&);
117
118 static std::false_type check(...);
119
120 using type = decltype(check(std::declval<T&>())); // NOLINT, false positive?
121 static constexpr bool value = type::value;
122};
123
124template <typename T>
126
127} // namespace detail
128
129} // namespace opcua
Template base class to wrap UA_* type objects.
constexpr TypeWrapper & operator=(T &&native) noexcept
Move assignment with native object.
constexpr void swap(TypeWrapper &other) noexcept
Swap with wrapper object.
constexpr void clear() noexcept
constexpr TypeWrapper(const TypeWrapper &other)
Copy constructor (deep copy).
static constexpr TypeIndex getTypeIndex()
Get type as type index of the UA_TYPES array.
constexpr TypeWrapper(const T &native)
Constructor with native object (deep copy).
constexpr TypeWrapper()=default
constexpr TypeWrapper & operator=(const T &native)
Copy assignment with native object (deep copy).
constexpr TypeWrapper(TypeWrapper &&other) noexcept
Move constructor.
constexpr void swap(T &native) noexcept
Swap with native object.
constexpr TypeWrapper(T &&native) noexcept
Constructor with native object (move rvalue).
constexpr TypeWrapper & operator=(TypeWrapper &&other) noexcept
Move assignment.
constexpr TypeWrapper & operator=(const TypeWrapper &other)
Copy assignment (deep copy).
Template base class to wrap native objects.
Definition wrapper.hpp:32
constexpr const T & native() const noexcept
Definition wrapper.hpp:75
constexpr Wrapper()=default
constexpr T copy(const T &src, const UA_DataType &type) noexcept(isPointerFree< T >)
constexpr bool isTypeWrapper
constexpr void clear(T &native, const UA_DataType &type) noexcept
uint16_t TypeIndex
Type index of the UA_TYPES array.
Definition common.hpp:21
static std::true_type check(const TypeWrapper< U, typeIndex > &)
decltype(check(std::declval< T & >())) type
static constexpr bool value
static std::false_type check(...)
const UA_DataType UA_TYPES[191]
#define UA_TYPES_COUNT