Index of /~TDDD38/exercises/Container_Design/src/Step_3

[ICO]NameLast modifiedSizeDescription

[PARENTDIR]Parent Directory  -  
[TXT]Container.h2015-02-11 09:42 1.0K 
[   ]Container.tcc2015-02-11 09:42 4.4K 
[   ]Makefile2015-02-11 09:42 595  
[TXT]README2015-02-11 09:42 2.8K 
[TXT]container-test.cc2015-02-11 09:42 2.5K 

README Container Design, Step 3
---------------------------------------------------------------------------------
From Step 2 we have exception-safe and exception-neutral versions of special
member functions for initializing, copying, moving, and destroying Container
objects.

Here we have added clear() and swap() functions, the latter in both a member
and a non-member version. The non-member overloading will be a better match 
for Containers than the generic std::swap(). We use these functions to simplify
the implementation of the move constructors, the copy assignment operator, and
the move assignment operator. 

The member swap is implemented using the standard library swap:

   template <typename T>
   void 
   Container<T>::
   swap(Container& other) nothrow
   {
      std::swap(elems_, other.elems_);
      std::swap(capacity_ , other.capacity_);
      std::swap(size_ , other.size_);
   }

The standard library swap guarantees not to throw, if the the argument type, T,
is nothrow move constructible and nothrow move assignable. Here we swap pointers
and their "copy constructor" and "copy assignment operator" cannot throw, so 
the member swap fulfills the nothrow guarantee. The non-member swap is implemented
using the member swap so also this swap fulfills the nothrow guarantee:

   template <typename T>
   void swap(Container<T>& a, Container<T>& b) nothrow
   {
      a.swap(b);
   }

The copy assignment operator is implemented using the "create a temporary and swap"
idiom (the self test can be excluded):

   template <typename T>
   Container<T>&
   Container<T>::
   operator=(const Container& other)
   {
      if (this != &other)
      {
         Container(other).swap(*this);
      }
      return *this;
   }

The only possible exception is from the copy constructor, which is fail-safe.

The move constructor lets the destination container be initialized according to
the initializers declared in the data member declarations, an empty container 
is created, and then swaps content with the other object. Nothing here can fail:

   template <typename T>
   Container<T>::
   Container(Container&& other)
   {
      swap(other);
  }

The move assignment operator first clears the left hand side container, making
it an empty container, and then swaps content with the right hand side container.
Nothing here can fail:

   template <typename T>
   Container<T>&
   Container<T>::
   operator=(Container&& other)
   {
      if (this != &other)
      {
         clear();
         swap(other);
      }
      return *this;
   }

So, we are still exception-safe and exception-neutral, and by adding clear() and
swap() we have made it possible to hide the details and reuse code in a nice way.

Still robust!
---------------------------------------------------------------------------------