/*! @file

    @id $Id$
*/
//       1         2         3         4         5         6         7         8
// 45678901234567890123456789012345678901234567890123456789012345678901234567890

#ifndef __SHARED_HXX__
#define __SHARED_HXX__

#include <mrw/checkcxx11.hxx>
#include <memory>

namespace mrw {

  //! Shared pointer with better usage than std::shared_ptr
  /*! You can assign a pointer or even construct like an auto variable. */
  template <typename T> class Shared: public std::shared_ptr<T> {
    public:
      //! Default empty construction
      Shared() {}
      Shared(T* t): std::shared_ptr<T>(std::shared_ptr<T>(t)) {}
      //! Construction from std::shared_ptr
      Shared(std::shared_ptr<T> t): std::shared_ptr<T>(t) {}
      //! Constructor creates child with one argument
      template <typename T1>
          Shared(T1 t1):
              std::shared_ptr<T>(new T(t1)) {
      }
      //! Constructor creates child with two arguments
      template <typename T1, typename T2>
          Shared(T1 t1, T2 t2):
              std::shared_ptr<T>(new T(t1, t2)) {
      }
      //! Constructor creates child with three arguments
      template <typename T1, typename T2, typename T3>
          Shared(T1 t1, T2 t2, T3 t3):
              std::shared_ptr<T>(new T(t1, t2, t3)) {
      }
      //! Constructor creates child with four arguments
      template <typename T1, typename T2, typename T3, typename T4>
          Shared(T1 t1, T2 t2, T3 t3, T4 t4):
              std::shared_ptr<T>(new T(t1, t2, t3, t4)) {
      }
      //! Constructor creates child with five arguments
      template <typename T1, typename T2, typename T3, typename T4, typename T5>
          Shared(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5):
              std::shared_ptr<T>(new T(t1, t2, t3, t4, t5)) {
      }
      //! Constructor creates child with six arguments
      template <typename T1, typename T2, typename T3, typename T4, typename T5,
                typename T6>
          Shared(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6):
              std::shared_ptr<T>(new T(t1, t2, t3, t4, t5, t6)) {
      }
      //! Constructor creates child with seven arguments
      template <typename T1, typename T2, typename T3, typename T4, typename T5,
                typename T6, typename T7>
          Shared(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7):
              std::shared_ptr<T>(new T(t1, t2, t3, t4, t5, t6, t7)) {
      }
      //! Constructor creates child with eight arguments
      template <typename T1, typename T2, typename T3, typename T4, typename T5,
                typename T6, typename T7, typename T8>
          Shared(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7, T8 t8):
              std::shared_ptr<T>(new T(t1, t2, t3, t4, t5, t6, t7, t8)) {
      }
      //! Constructor creates child with nine arguments
      template <typename T1, typename T2, typename T3, typename T4, typename T5,
                typename T6, typename T7, typename T8, typename T9>
          Shared(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7, T8 t8, T9 t9):
              std::shared_ptr<T>(new T(t1, t2, t3, t4, t5, t6, t7, t8, t9)) {
      }
      //! Assign from shared pointer
      Shared& operator=(std::shared_ptr<T> t) {
        std::shared_ptr<T>::operator=(t);
        return *this;
      }
      //! Assign from pointer
      Shared& operator=(T* t) {
        std::shared_ptr<T>::operator=(std::shared_ptr<T>(t));
        return *this;
      }
  };
  
}

#endif
