samedi 21 avril 2018

What's a reason to provide a swap() for the user defined type?

For example, I have a class which manages a POSIX fd:

class remote_connection:
{
public:
  explicit remote_connection( int socket_fd ) : socket_fd(socket_fd) {}
  ~remote_connection() { close( socket_fd); }

  /* no copy semantic */
  remote_connection( const remote_connection& other ) = delete;
  remote_connection& operator=( const remote_connection& rhs ) = delete;

  remote_connection( remote_connection&& other )
  {
    socket_fd = other.socket_fd;
    other.socket_fd = -1;
  }

  remote_connection& operator=( remote_connection&& rhs )
  {
    close( socket_fd );
    socket_fd = rhs.socket_fd;

    rhs.socket_fd = -1;

    return *this;
  } 

private:
  int socket_fd;
};

And somewhere in code:

/* let '42' and '24' be a valid fds */
remote_connection cl_1( 42 ), cl_2( 24 );

...

using std::swap;

swap( cl_1, cl_2 );

For such an implementation of a remote_connection ADL has found no user defined swap and fall-backs to the std namespace where there's no specialization for the remote_connection, so compiler instantiates a std::swap< remote_connection >() function from a std::swap< T >() template function. That function implementation invokes move ctor and move assignment operator which causes objects to exchange their content.

I could implement a swap() for the remote_connection that would result in the SAME result.

So the question is what can I do so specific within swap for the class that a template std::swap< T >() can't? Or why we should provide an implementation for a type if it can be instantiated by a compiler even for types which manage not trivial sub-objects (POSIX fd, pointers,...)?

Aucun commentaire:

Enregistrer un commentaire