#pragma once #include #include #include // Specializations must Free to release a reference // Specializations can implement UpRef to increase a reference count on copy template struct RefTraits {}; template <> struct RefTraits { static constexpr void (*Free)(EVP_PKEY*) = EVP_PKEY_free; static constexpr int (*UpRef)(EVP_PKEY*) = EVP_PKEY_up_ref; }; template <> struct RefTraits { static constexpr void (*Free)(X509*) = X509_free; static constexpr int (*UpRef)(X509*) = X509_up_ref; }; template <> struct RefTraits { static constexpr void (*Free)(EVP_PKEY_CTX*) = EVP_PKEY_CTX_free; // this type does not implement UpRef }; template struct RefDeleter { auto operator()(T *ptr) const -> void { RefTraits::Free(ptr); } }; template struct Ref : std::unique_ptr> { using base = std::unique_ptr>; /// Owns nothing Ref() noexcept = default; /// Takes ownership of the pointer explicit Ref(T *x) noexcept : base{x} {} Ref(Ref &&ref) noexcept = default; Ref(const Ref &ref) noexcept { *this = ref; } Ref &operator=(Ref&&) noexcept = default; Ref &operator=(const Ref &ref) noexcept { if (ref) { RefTraits::UpRef(ref.get()); } this->reset(ref.get()); return *this; } };