//Damian Zawadzki 206202 T-SST


//biblioteka boost - boost::ref


#include<iostream>
#include<vector>
#include<list>
#include<boost/ref.hpp>
using namespace std;

//szablon funkcji
template<class T> 
void g(T t) 
{
  //sprawdzenie czy przekazany typ przekazanego obiektu to reference_wrapper 
  if (boost::is_reference_wrapper<T>::value) 
  cout << "type is reference wrapper" << endl; 
  t++; 
}

template<class T>
void g_Wrap(T t)
{ 
  //kopia obiketu typu reference_wrapper 
  T t_(t);
  t_++;
}


template<class T>
void g_unWrap(T t)
{ 
  //wykonanie unwrap zwraca typ zwykły zdejmując referencje
  typename boost::unwrap_reference<T>::type t_=t;
  t_++;
}

template<class T>
void g_const(T t)
{
  cout << t << endl;
}

typedef list<int> numbers;
typedef vector<boost::reference_wrapper<int> > 
 number_refs; //wektor referencji do obiektów typu int


 int main()
{
 int i = 0;

 g(i); //przekazanie zmiennej "i" przez wartość
 cout << i << endl; //tak jak oczekujemy, 0 
 g(boost::ref(i)); //powiązanie referencji do zmiennj "i" i przekazanie jej jako argument
 cout << i << endl; // wyjście: 1
 g_const(boost::cref(i)); //powiązanie stałej referencji do "i" i przekazanie jej jako argument
 g_Wrap(boost::ref(i)); //zwieksza wartość "i" o 1
 cout << i << endl; // wyjście: 2
 g_unWrap(boost::ref(i));//wykonanie unwrap_reference na typie powoduje że "i" nie bedzie zwiekszane
 cout << i << endl; // wyjście: 2

 numbers  num;//deklaracja listy
 number_refs num_refs;//deklaracja wektora z reference wrapper

 for(int i = 0; i < 10; ++i) 
{
 num.push_back(2*i*i^4 - 8*i + 7); //zwykłe obiekty int dodawane do listy
 num_refs.push_back(
//stworzenie referencji do ostatniego elementu w liscie num
  boost::ref(num.back()));
}
 //posortowanie liczb w wektorze referencji do tychże liczb
 sort(num_refs.begin(), num_refs.end());

 //wypisanie posortowanych liczb z wectora i zmiana jednej z nich
 for (number_refs::iterator it=num_refs.begin() ; it < num_refs.end(); it++ )
   {if (*it==-109) (*it)++; cout << *it << " ";}
 cout << endl;
 
 //wypisanie nieposortowanych liczb z listy 
 for (numbers::iterator it=num.begin() ; it != num.end(); it++ )
 //wartość zmieniona w wektorze referencji została także zmieniona w liscie obiektów
   { cout << *it << " ";
   }
 cout << endl;
  return 0;
}

