What wrapper class in C++ should I use for automated resource management?

前端 未结 8 1127
余生分开走
余生分开走 2020-12-16 13:56

I\'m a C++ amateur. I\'m writing some Win32 API code and there are handles and weirdly compositely allocated objects aplenty. So I was wondering - is there some wrapper clas

8条回答
  •  没有蜡笔的小新
    2020-12-16 14:22

    template 
    class unique_handle
    {
        using pointer = typename Traits::pointer;
    
        pointer m_value;
    
        auto close() throw() -> void
        {
            if (*this)
            {
                Traits::close(m_value);
            }
        }
    
    public:
    
        unique_handle(unique_handle const &) = delete;
        auto operator=(unique_handle const &)->unique_handle & = delete;
    
        explicit unique_handle(pointer value = Traits::invalid()) throw() :
            m_value{ value }
        {
        }
    
        unique_handle(unique_handle && other) throw() :
            m_value{ other.release() }
        {
        }
    
        auto operator=(unique_handle && other) throw() -> unique_handle &
        {
            if (this != &other)
            {
                reset(other.release());
            }
    
            return *this;
        }
    
        ~unique_handle() throw()
        {
            close();
        }
    
        explicit operator bool() const throw()
        {
            return m_value != Traits::invalid();
        }
    
        auto get() const throw() -> pointer
        {
            return m_value;
        }
    
        auto get_address_of() throw() -> pointer *
        {
            ASSERT(!*this);
            return &m_value;
        }
    
        auto release() throw() -> pointer
        {
            auto value = m_value;
            m_value = Traits::invalid();
            return value;
        }
    
        auto reset(pointer value = Traits::invalid()) throw() -> bool
        {
            if (m_value != value)
            {
                close();
                m_value = value;
            }
    
            return static_cast(*this);
        }
    
        auto swap(unique_handle & other) throw() -> void
        {
            std::swap(m_value, other.m_value);
        }
    };
    
    template 
    auto swap(unique_handle & left,
        unique_handle & right) throw() -> void
    {
        left.swap(right);
    }
    
    template 
    auto operator==(unique_handle const & left,
        unique_handle const & right) throw() -> bool
    {
        return left.get() == right.get();
    }
    
    template 
    auto operator!=(unique_handle const & left,
        unique_handle const & right) throw() -> bool
    {
        return left.get() != right.get();
    }
    
    template 
    auto operator<(unique_handle const & left,
        unique_handle const & right) throw() -> bool
    {
        return left.get() < right.get();
    }
    
    template 
    auto operator>=(unique_handle const & left,
        unique_handle const & right) throw() -> bool
    {
        return left.get() >= right.get();
    }
    
    template 
    auto operator>(unique_handle const & left,
        unique_handle const & right) throw() -> bool
    {
        return left.get() > right.get();
    }
    
    template 
    auto operator<=(unique_handle const & left,
        unique_handle const & right) throw() -> bool
    {
        return left.get() <= right.get();
    }
    
    struct null_handle_traits
    {
        using pointer = HANDLE;
    
        static auto invalid() throw() -> pointer
        {
            return nullptr;
        }
    
        static auto close(pointer value) throw() -> void
        {
            VERIFY(CloseHandle(value));
        }
    };
    
    struct invalid_handle_traits
    {
        using pointer = HANDLE;
    
        static auto invalid() throw() -> pointer
        {
            return INVALID_HANDLE_VALUE;
        }
    
        static auto close(pointer value) throw() -> void
        {
            VERIFY(CloseHandle(value));
        }
    };
    
    using null_handle = unique_handle;
    using invalid_handle = unique_handle;
    

提交回复
热议问题