代码之家  ›  专栏  ›  技术社区  ›  user877329

通用句柄类

  •  3
  • user877329  · 技术社区  · 10 年前

    我偶然发现了这个问题: Using unique_ptr to control a file descriptor 这个 std::unique_ptr 对于一般手柄来说并不合适。更普通的班级也是如此

    template<class HandleType,HandleType nullvalue,class Deleter>
    class Handle;
    

    已经实现了(可能是增强版),或者我应该自己动手。这个问题以前在中提出过 What wrapper class in C++ should I use for automated resource management? ,但现在我们有了C++14,所以可以有更多的选择。

    我还发现了以下建议: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3677.html 所以其他人也考虑过这个问题。

    1 回复  |  直到 9 年前
        1
  •  3
  •   milleniumbug R. Martinho Fernandes    10 年前

    C++标准中还没有这样的类,所以我决定 write my own :

    template<typename Policy>
    class unique_handle
    {
        typename Policy::handle_type h;
    
    public:
        unique_handle(const unique_handle&) = delete;
    
        typename Policy::handle_type get() const
        {
            return h;
        }
    
        typename Policy::handle_type release()
        {
            typename Policy::handle_type temp = h;
            h = Policy::get_null();
            return temp;
        }
    
        explicit operator bool() const
        {
            return !Policy::is_null(h);
        }
    
        bool operator!() const
        {
            return !static_cast<bool>(*this);
        }
    
        void reset(typename Policy::handle_type new_handle)
        {
            typename Policy::handle_type old_handle = h;
            h = new_handle;
            if(!Policy::is_null(old_handle))
            {
                Policy::close(old_handle);
            }
        }
    
        void swap(unique_handle& other)
        {
            std::swap(this->h, other.h);
        }
    
        void reset()
        {
            reset(Policy::get_null());
        }
    
        ~unique_handle()
        {
            reset();
        }
    
        unique_handle& operator=(unique_handle other) noexcept
        {
            this->swap(other);
            return *this;
        }
    
        unique_handle(unique_handle&& other) noexcept
        {
            this->h = other.h;
            other.h = Policy::get_null();
        }
    
        unique_handle()
        {
            h = Policy::get_null();
        }
    
        unique_handle(typename Policy::handle_type handle)
        {
            h = handle;
        }
    };
    

    示例用法:

    #include <wiertlo/unique_handle.hpp>
    #include <iostream>
    #include <cassert>
    #include <unistd.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    
    struct file_descriptor_policy
    {
        typedef int handle_type;
        static void close(handle_type handle)
        {
            ::close(handle);
        }
    
        static handle_type get_null()
        {
            return -1;
        }
    
        static bool is_null(handle_type handle)
        {
            return handle == -1;
        }
    };
    
    int main()
    {
        typedef wiertlo::unique_handle<file_descriptor_policy> file_descriptor;
        file_descriptor null_fd; // null file descriptor
        assert(!null_fd);
        file_descriptor fd(open("/dev/null", O_WRONLY));
        assert(fd);
        write(fd.get(), "test", 4);
        file_descriptor other = std::move(fd);
        assert(!fd);
        assert(other);
    }