Using unique_ptr to control a file descriptor

前端 未结 9 2072
無奈伤痛
無奈伤痛 2020-12-10 05:29

In theory, I should be able to use a custom pointer type and deleter in order to have unique_ptr manage an object that is not a pointer. I tried the following c

相关标签:
9条回答
  • 2020-12-10 05:52

    Found an answer at cppreference.com. Look in the examples code:

        void close_file(std::FILE* fp) { std::fclose(fp); }
        ...
        {
          std::unique_ptr<std::FILE, decltype(&close_file)> fp(std::fopen("demo.txt",                                                             
                                                                          "r"), 
                                                               &close_file);
          if(fp)     // fopen could have failed; in which case fp holds a null pointer
             std::cout << (char)std::fgetc(fp.get()) << '\n';
        }// fclose() called here, but only if FILE* is not a null pointer
         // (that is, if fopen succeeded)
    

    Tried it in vs2019 and it works! Also tried it with member and lambda:

    FileTest.h:

    class A
    {
      std::unique_ptr<std::FILE, std::function<void(std::FILE*)>> fp;
    }
    

    FileTest.cpp

    void A::OpenFile(const char* fname)
    {
        fp = std::unique_ptr < std::FILE, std::function<void(std::FILE*)>>(
            std::fopen(fname, "wb"),
            [](std::FILE * fp) { std::fclose(fp); });
    }
    
    0 讨论(0)
  • 2020-12-10 05:56

    The type exposed by the Deleter::pointer must satisfy the NullablePointer requirements. Chief among them, this expression must be legal: Deleter::pointer p = nullptr;. Of course, nullptr is pretty much defined by the fact that it cannot be implicitly converted to a number, thus this doesn't work.

    You'll have to use a type which can be implicitly constructed with std::nullptr_t. Something like this:

    struct file_desc
    {
      file_desc(int fd) : _desc(fd) {}
      file_desc(std::nullptr_t) : _desc(-1) {}
    
      operator int() {return _desc;}
    
      bool operator ==(const file_desc &other) const {return _desc == other._desc;}
      bool operator !=(const file_desc &other) const {return _desc != other._desc;}
      bool operator ==(std::nullptr_t) const {return _desc == -1;}
      bool operator !=(std::nullptr_t) const {return _desc != -1;}
    
      int _desc;
    };
    

    You can use that as the Deleter::pointer type.

    0 讨论(0)
  • 2020-12-10 05:57

    The open source Android Framework defines a unique_fd class that might meet your needs: https://android.googlesource.com/platform/system/core/+/c0e6e40/base/include/android-base/unique_fd.h

    0 讨论(0)
提交回复
热议问题