#ifndef ROW_HPP
#define ROW_HPP

#include <iostream>
#include <cstdint>
#include <stdexcept>
#include "sort_algorithms.hpp"


template<typename T>
class row {
private:
	T* p;
	uint32_t n;

public:

/* ======================
   CONSTRUCTOR
   ======================*/
  row(T* arr, uint32_t size){
  	n = size;
  	p = new T[n];

  	for (uint32_t i=0;i<n;i++)
  		p[i] = arr[i];
  	
	  
}

/*=======================
DESTRUCTOR
=========================*/

  ~row() {
  	delete[] p;
  }
  

/* ==============================
   COPY CONSTRUCTOR 
   ==============================*/
   row(const row& other) {
   	n = other.n;
   	p = new T[n];

   	for (uint32_t i =0;i <n; i++)
   		p[i] = other.p[i];
   	}

/* ============================
 ASSIGMENT OPERATOR
 ===============================*/
 
 row& operator=(const row& other) {

    	if(this!= &other) {
    		delete[] p;

    		n = other.n;
    		p = new T[n];

    		for (uint32_t i =0;i <n;i++){
    			p[i] = other.p[i];
    		}
	}
    		return *this;
   }
/* ================================
   SIZE
   ================================*/

uint32_t size() const
{
	return n;
}

 
 /* ===================================
 OPERATOR[]
 ======================================*/
 
 T& operator[](uint32_t idx){
 	return p[idx];
 }
 
 const T& operator[](uint32_t idx) const {
 	return p[idx];
 }
 
/* ==========================================
   OPERATOR AT
   ==========================================*/
   
 T& at(uint32_t idx ){
		 
	 if (idx >=n)
	 	throw std::out_of_range("Out of range");

	 return p[idx];
}


/* ============================
   OUTPUT 
   ============================*/
   
friend std::ostream& operator<<(std::ostream& os, const row& r)
{
	for(uint32_t i =0; i<r.n;i++)
		os <<r.p[i] << "  ";
	return os;
}

/* ==============================
   INPUT 
   =============================*/
   
friend std::istream& operator>>(std::istream& is, row& r)
{
	for (uint32_t i =0;i < r.n;i++)
		is >> r.p[i];
	return is;
	}
	
};

#endif	
		

