53 static_assert(std::is_copy_constructible_v<T>);
54 static_assert(std::is_nothrow_move_constructible_v<T>);
55 static_assert(std::is_nothrow_default_constructible_v<T>);
57 static constexpr T
copy(
const T&
object) {
61 static constexpr T
move(T&&
object)
noexcept {
62 return std::move(
object);
74template <
typename T, TypeIndex Index>
78 static constexpr T
copy(
const T& native) {
79 return detail::copy(native,
UA_TYPES[Index]);
82 static constexpr T
move(T&& native)
noexcept {
83 return std::exchange(native, {});
86 static constexpr void clear(T& native)
noexcept {
87 detail::clear(native,
UA_TYPES[Index]);
93template <
typename Handler,
typename T,
typename =
void>
94struct HasClear : std::false_type {};
96template <
typename Handler,
typename T>
97struct HasClear<Handler, T, std::void_t<decltype(Handler::clear(std::declval<T&>()))>>
100template <
typename WrapperType,
bool Clear>
101class WrapperDestructorMixin {};
103template <
typename WrapperType>
104class WrapperDestructorMixin<WrapperType, true> {
106 ~WrapperDestructorMixin() noexcept {
107 auto& native = *
static_cast<WrapperType*
>(
this)->handle();
108 WrapperType::HandlerType::clear(native);
131template <
typename T,
typename Handler = TypeHandler<T>>
133 :
public detail::WrapperDestructorMixin<
135 detail::HasClear<Handler, T>::value> {
137 static_assert(std::is_nothrow_default_constructible_v<T>);
138 static_assert(std::is_invocable_v<
decltype(Handler::copy),
const T&>);
139 static_assert(std::is_nothrow_invocable_v<
decltype(Handler::move), T&&>);
148 : native_{Handler::copy(other.native())} {}
152 : native_{Handler::copy(
native)} {}
156 : native_{Handler::move(std::move(other.native()))} {}
160 : native_{Handler::move(std::move(
native))} {}
166 if (
this != &other) {
168 this->
native() = Handler::copy(other.native());
175 if (&this->
native() != &native) {
184 if (
this != &other) {
186 this->
native() = Handler::move(std::move(other.native()));
201 constexpr operator T&()
noexcept {
206 constexpr operator const T&()
const noexcept {
226 constexpr const T*
handle() const noexcept {
243 constexpr const T&
native() const noexcept {
252 if constexpr (detail::HasClear<Handler, T>::value) {
253 Handler::clear(native_);
267template <
typename T, TypeIndex Index>
270template <
typename T, TypeIndex Index>
286 template <
typename U,
typename Handler>
291 static constexpr bool value = type::value;
299using IsPointerInterconvertibleWrapper = std::conjunction<
301 std::is_standard_layout<T>,
302 std::is_standard_layout<typename T::NativeType>,
303 std::bool_constant<
sizeof(T) ==
sizeof(
typename T::NativeType)>>;
312constexpr T*
asWrapper(
typename T::NativeType* native)
noexcept {
313 static_assert(detail::IsPointerInterconvertibleWrapper<T>::value);
314 return static_cast<T*
>(
static_cast<void*
>(native));
320constexpr const T*
asWrapper(
const typename T::NativeType* native)
noexcept {
321 static_assert(detail::IsPointerInterconvertibleWrapper<T>::value);
322 return static_cast<const T*
>(
static_cast<const void*
>(native));
328constexpr T&
asWrapper(
typename T::NativeType& native)
noexcept {
329 return *asWrapper<T>(&native);
335constexpr const T&
asWrapper(
const typename T::NativeType& native)
noexcept {
336 return *asWrapper<T>(&native);
342constexpr typename T::NativeType*
asNative(T* wrapper)
noexcept {
343 static_assert(detail::IsPointerInterconvertibleWrapper<T>::value);
344 return static_cast<typename T::NativeType*
>(
static_cast<void*
>(wrapper));
350constexpr const typename T::NativeType*
asNative(
const T* wrapper)
noexcept {
351 static_assert(detail::IsPointerInterconvertibleWrapper<T>::value);
352 return static_cast<const typename T::NativeType*
>(
static_cast<const void*
>(wrapper));
358constexpr typename T::NativeType&
asNative(T& wrapper)
noexcept {
365constexpr const typename T::NativeType&
asNative(
const T& wrapper)
noexcept {
376 std::enable_if_t<IsWrapper<T>::value && IsRegistered<typename T::NativeType>::value>> {
static constexpr TypeIndex typeIndex()
Template base class to wrap (native) objects.
constexpr Wrapper & operator=(T &&native) noexcept
Move assignment with native object.
constexpr Wrapper & operator=(const T &native)
Copy assignment with native object.
~Wrapper() noexcept=default
constexpr T * handle() noexcept
Return pointer to native object.
constexpr Wrapper(T &&native) noexcept
Move constructor with native object.
constexpr const T & native() const noexcept
constexpr Wrapper() noexcept=default
constexpr void clear() noexcept
constexpr Wrapper(const T &native)
Copy constructor with native object.
constexpr const T * handle() const noexcept
Return pointer to native object.
constexpr Wrapper(Wrapper &&other) noexcept
Move constructor.
constexpr void swap(T &native) noexcept
Swap with native object.
constexpr void swap(Wrapper &other) noexcept
Swap with wrapper object.
constexpr Wrapper & operator=(Wrapper &&other) noexcept
Move assignment.
constexpr T * operator->() noexcept
Member access to native object.
constexpr T & native() noexcept
constexpr const T * operator->() const noexcept
Member access to native object.
constexpr T & asWrapper(typename T::NativeType &native) noexcept
Cast native object references to Wrapper object references.
constexpr const T * asWrapper(const typename T::NativeType *native) noexcept
Cast native object pointers to Wrapper object pointers.
constexpr const T & asWrapper(const typename T::NativeType &native) noexcept
Cast native object references to Wrapper object references.
constexpr T::NativeType * asNative(T *wrapper) noexcept
Cast Wrapper object pointers to native object pointers.
constexpr T * asWrapper(typename T::NativeType *native) noexcept
Cast native object pointers to Wrapper object pointers.
constexpr const T::NativeType * asNative(const T *wrapper) noexcept
Cast Wrapper object pointers to native object pointers.
constexpr T::NativeType & asNative(T &wrapper) noexcept
Cast Wrapper object references to native object references.
constexpr const T::NativeType & asNative(const T &wrapper) noexcept
Cast Wrapper object references to native object references.
uint16_t TypeIndex
Type index of the UA_TYPES array.
decltype(check(std::declval< T & >())) type
static std::false_type check(...)
static constexpr bool value
static std::true_type check(const Wrapper< U, Handler > &)
Specialized type handler for native types.
static constexpr T copy(const T &native)
static constexpr void clear(T &native) noexcept
static constexpr T move(T &&native) noexcept
Default type handler providing standard copy and move operations.
static constexpr T copy(const T &object)
static constexpr T move(T &&object) noexcept
static const UA_DataType & getDataType() noexcept
const UA_DataType UA_TYPES[191]