0

I have created a class which contains a socket that connects to a client and sends information as it becomes available. I have also in this project built an SQL connection which uses an unique_ptr to ensure the memory doesn't leak when the class it belongs to goes out of scope:

 #include <memory>
 #include <sqlite3.h> 

 typedef std::unique_ptr<sqlite3, decltype(&sqlite3_close)> Database;
 typedef std::unique_ptr<sqlite3_stmt, decltype(&sqlite3_finalize)> Statement;

This works fine, and I can construct both types with brace initializers.

I wish to do this for a socket using socket.h, I have the code working fine with the socket defined locally within my function, but I would prefer to allocate it to the heap and store it safely in a smart pointer so that it will always be closed down when the class is destroyed or it goes out of scope:

#include <unistd.h>
#include <memory>

typedef std::unique_ptr<int, decltype(&close)> Socket;

Which I then try to invoke using:

Socket open_socket()
{
    int *sock = new int(socket(AF_INET, SOCK_STREAM, 0));
    return Socket{sock, close};
};
error: invalid conversion from ‘std::remove_reference<int*&>::type’ {aka ‘int*’} to ‘int’ [-fpermissive]
  360 |    get_deleter()(std::move(__ptr));
      |    ~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~
      |                 |
      |                 std::remove_reference<int*&>::type {aka int*}

I am trying to compile c++17 on arch linux using gcc.

Is there a way to do this without having to wrap the socket in another class?

Edit: The linked post relating to a file handle still doesn't answer my question of whether or not this is possible with simply a smart pointer. I have implemented a wrapper class however I'm still interested to know if it can be done using a unique_ptr.

class Socket {
public:
    Socket( ) {
        sock_ = socket(AF_INET, SOCK_STREAM, 0);
    };
           
    ~Socket( ) {
        close(sock_);
    };

    Socket(Socket &&) = default;
    Socket(const Socket&) = delete;
    Socket &operator=(const Socket&) = delete;
    Socket &operator=(Socket &&) = delete;

    void bind(....) {
        ...
    };
    
private:
    int sock_;
}:
frazb
  • 76
  • 2
  • 3
    How about creating a SocketHolder class that holds the file-descriptptor as a member-variable and calls `close(m_fd);` in its destructor-method? With that approach, no custom deleter specifications are necessary; you can just declare a `std::unique_ptr` in the usual way. – Jeremy Friesner Jul 27 '20 at 21:59
  • And with a `SocketHolder` the intent of the code is brutally obvious to all but the most clueless of readers. Probably won't need the smart pointer at all. – user4581301 Jul 27 '20 at 22:07
  • >user4581301 the `SocketHolder` should be move-only with a destructor . – Red.Wave Jul 28 '20 at 04:07

0 Answers0