diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/Makefile.am | 2 | ||||
| -rw-r--r-- | src/meson.build | 1 | ||||
| -rw-r--r-- | src/stdplus/handle/copyable.hpp | 112 |
3 files changed, 115 insertions, 0 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index 57af82a..d45007e 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -4,6 +4,8 @@ lib_LTLIBRARIES = libstdplus.la libstdplus_la_SOURCES = libstdplus_la_LIBADD = $(COMMON_LIBS) +nobase_include_HEADERS += stdplus/handle/copyable.hpp + nobase_include_HEADERS += stdplus/handle/managed.hpp nobase_include_HEADERS += stdplus/signal.hpp diff --git a/src/meson.build b/src/meson.build index 6b1fea9..a6ff714 100644 --- a/src/meson.build +++ b/src/meson.build @@ -20,5 +20,6 @@ install_headers( subdir: 'stdplus') install_headers( + 'stdplus/handle/copyable.hpp', 'stdplus/handle/managed.hpp', subdir: 'stdplus/handle') diff --git a/src/stdplus/handle/copyable.hpp b/src/stdplus/handle/copyable.hpp new file mode 100644 index 0000000..df383db --- /dev/null +++ b/src/stdplus/handle/copyable.hpp @@ -0,0 +1,112 @@ +#pragma once +#include <optional> +#include <stdplus/handle/managed.hpp> +#include <utility> + +namespace stdplus +{ + +/** @brief Similar to the Managed Handle, but also allows for copying + * and performs an operation during that copy. + */ +template <typename T, typename... As> +struct Copyable +{ + template <void (*drop)(T&&, As&...), T (*ref)(const T&, As&...)> + class Handle : public Managed<T, As...>::template Handle<drop> + { + public: + using MHandle = typename Managed<T, As...>::template Handle<drop>; + + /** @brief Creates a handle referencing the object + * + * @param[in] maybeV - Optional object being managed + */ + template <typename... Vs> + constexpr explicit Handle(const std::optional<T>& maybeV, Vs&&... vs) : + MHandle(std::nullopt, std::forward<Vs>(vs)...) + { + reset(maybeV); + } + template <typename... Vs> + constexpr explicit Handle(const T& maybeV, Vs&&... vs) : + MHandle(std::nullopt, std::forward<Vs>(vs)...) + { + reset(maybeV); + } + + /** @brief Creates a handle owning the object + * + * @param[in] maybeV - Maybe the object being managed + */ + template <typename... Vs> + constexpr explicit Handle(std::optional<T>&& maybeV, + Vs&&... vs) noexcept : + MHandle(std::move(maybeV), std::forward<Vs>(vs)...) + { + } + template <typename... Vs> + constexpr explicit Handle(T&& maybeV, Vs&&... vs) noexcept : + MHandle(std::move(maybeV), std::forward<Vs>(vs)...) + { + } + + constexpr Handle(const Handle& other) : MHandle(std::nullopt, other.as) + { + reset(other.maybe_value()); + } + + constexpr Handle(Handle&& other) noexcept : MHandle(std::move(other)) + { + } + + constexpr Handle& operator=(const Handle& other) + { + if (this != &other) + { + reset(); + this->as = other.as; + reset(other.maybe_value()); + } + return *this; + } + + constexpr Handle& operator=(Handle&& other) noexcept + { + MHandle::operator=(std::move(other)); + return *this; + } + + using MHandle::reset; + + /** @brief Resets the managed value to a new value + * Takes a new reference on the value + * + * @param[in] maybeV - Maybe the new value + */ + constexpr void reset(const std::optional<T>& maybeV) + { + if (maybeV) + { + reset(doRef(*maybeV, std::index_sequence_for<As...>())); + } + else + { + reset(std::nullopt); + } + } + constexpr void reset(const T& maybeV) + { + reset(doRef(maybeV, std::index_sequence_for<As...>())); + } + + private: + template <size_t... Indices> + T doRef(const T& v, std::index_sequence<Indices...>) + { + return ref(v, std::get<Indices>(this->as)...); + } + }; +}; + +} // namespace stdplus |

