diff options
| author | William A. Kennington III <wak@google.com> | 2018-11-02 17:29:15 -0700 |
|---|---|---|
| committer | William A. Kennington III <wak@google.com> | 2019-03-29 21:14:57 +0000 |
| commit | e847ef8bbd5accd36a3287c686894418721c6798 (patch) | |
| tree | 551abef5024682e55fcca07fc26a60ac4ac2f379 /src | |
| parent | 7a5e23259a696bf240a14200535680b42c445096 (diff) | |
| download | stdplus-e847ef8bbd5accd36a3287c686894418721c6798.tar.gz stdplus-e847ef8bbd5accd36a3287c686894418721c6798.zip | |
handle/copyable: Implement copyable handle
This is a generic handle type that holds a resource and uses RAII to
call a user defined function when the resource is copied or destroyed.
Tested:
Built and run through unit tests.
Change-Id: I3d23544b2e7c8d8c6686effc03b3b7433ea18bf5
Signed-off-by: William A. Kennington III <wak@google.com>
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 |

