17 Bjarne Book

Streszczenie ciekawych tematów z książki Bjarnego
C++. Podróż po języku dla zaawansowanych. Wydanie II

Okładka książki/ebooka C++. Podróż po języku dla zaawansowanych. Wydanie II
...

    1. Podstawy 11
    • 1.1. Wprowadzenie 11
    • 1.2. Programy 12
    • 1.3. Funkcje 14
    • 1.4. Typy, zmienne i arytmetyka 15
    • 1.5. Zakres i cykl istnienia 19
    • 1.6. Stałe 20
    • 1.7. Wskaźniki, tablice i referencje 21
    • 1.8. Testy 24
    • 1.9. Mapowanie sprzętowe 27
    • 1.10. Porady 29
    2. Typy zdefiniowane przez użytkownika 31
    • 2.1. Wprowadzenie 31
    • 2.2. Struktury 32
    • 2.3. Klasy 33
    • 2.4. Unie 35
    • 2.5. Wyliczenia 36
    • 2.6. Porady 38
    3. Moduły 39
    • 3.1. Wprowadzenie 39
    • 3.2. Kompilacja rozdzielna 40
    • 3.3. Moduły (C++20) 42
    • 3.4. Przestrzenie nazw 44
    • 3.5. Obsługa błędów 45
    • 3.6. Argumenty i wartości zwrotne funkcji 52
    • 3.7. Porady 56
    4. Klasy 59
    • 4.1. Wprowadzenie 59
    • 4.2. Typy konkretne 60
    • 4.3. Typy abstrakcyjne 66
    • 4.4. Funkcje wirtualne 69
    • 4.5. Hierarchie klas 70
    • 4.6. Porady 76
    5. Operacje podstawowe 79
    • 5.1. Wprowadzenie 79
    • 5.2. Kopiowanie i przenoszenie 82
    • 5.3. Zarządzanie zasobami 87
    • 5.4. Operacje standardowe 88
    • 5.5. Porady 92
    6. Szablony 93
    • 6.1. Wprowadzenie 93
    • 6.2. Typy parametryzowane 94
    • 6.3. Operacje parametryzowane 98
    • 6.4. Mechanizmy szablonów 103
    • 6.5. Porady 106
    7. Koncepcje i programowanie generyczne 107
    • 7.1. Wprowadzenie 107
    • 7.2. Koncepcje (C++20) 108
    • 7.3. Programowanie generyczne 113
    • 7.4. Szablony zmienne 116
    • 7.5. Model kompilacji szablonów 119
    • 7.6. Porady 120
    8. Podstawowe informacje o bibliotece 121
    • 8.1. Wprowadzenie 121
    • 8.2. Komponenty biblioteki standardowej 122
    • 8.3. Nagłówki i przestrzeń nazw biblioteki standardowej 123
    • 8.4. Porady 124
    9. Łańcuchy i wyrażenia regularne 127
    • 9.1. Wprowadzenie 127
    • 9.2. Łańcuchy 128
    • 9.3. Widoki łańcuchów 130
    • 9.4. Wyrażenia regularne 132
    • 9.5. Porady 139
    10. Wejście i wyjście 141
    • 10.1. Wprowadzenie 141
    • 10.2. Wyjście 142
    • 10.3. Wejście 143
    • 10.4. Stan wejścia i wyjścia 145
    • 10.5. Wejście i wyjście typów zdefiniowanych przez użytkownika 146
    • 10.6. Formatowanie 147
    • 10.7. Strumienie plikowe 148
    • 10.8. Strumienie łańcuchowe 149
    • 10.9. Wejście i wyjście w stylu języka C 150
    • 10.10. System plików 150
    • 10.11. Porady 154
    11. Kontenery 157
    • 11.1. Wprowadzenie 157
    • 11.2. Typ vector 158
    • 11.3. Listy 162
    • 11.4. Słowniki 164
    • 11.5. Słowniki nieuporządkowane 165
    • 11.6. Przegląd kontenerów 167
    • 11.7. Porady 169
    12. Algorytmy 171
    • 12.1. Wprowadzenie 171
    • 12.2. Zastosowania iteratorów 173
    • 12.3. Typy iteratorów 175
    • 12.4. Iteratory strumieni 176
    • 12.5. Predykaty 178
    • 12.6. Przegląd algorytmów 178
    • 12.7. Koncepcje (C++20) 179
    • 12.8. Algorytmy kontenerów 183
    • 12.9. Algorytmy równoległe 184
    • 12.10. Porady 185
    13. Narzędzia pomocnicze 187
    • 13.1. Wprowadzenie 187
    • 13.2. Zarządzanie zasobami 188
    • 13.3. Sprawdzanie zakresu - gsl::span 193
    • 13.4. Kontenery specjalne 194
    • 13.5. Alternatywy 199
    • 13.6. Alokatory 203
    • 13.7. Czas 204
    • 13.8. Adaptacja funkcji 205
    • 13.9. Funkcje typów 206
    • 13.10. Porady 210
    14. Liczby 213
    • 14.1. Wprowadzenie 213
    • 14.2. Funkcje matematyczne 214
    • 14.3. Algorytmy numeryczne 215
    • 14.4. Liczby zespolone 216
    • 14.5. Liczby losowe 217
    • 14.6. Arytmetyka wektorowa 219
    • 14.7. Granice numeryczne 219
    • 14.8. Porady 220
    15. Współbieżność 221
    • 15.1. Wprowadzenie 221
    • 15.2. Zadania i wątki 222
    • 15.3. Przekazywanie argumentów 223
    • 15.4. Zwracanie wyników 224
    • 15.5. Wspólne używanie danych 225
    • 15.6. Oczekiwanie na zdarzenia 227
    • 15.7. Komunikacja między zadaniami 228
    • 15.8. Porady 232
    16. Historia i zgodność 235
    • 16.1. Historia 235
    • 16.2. Ewolucja funkcjonalności C++ 244
    • 16.3. Zgodność C i C++ 248
    • 16.4. Bibliografia 252
    • 16.5. Porady 255
    Indeks 257
    Skorowidz 259

16 ZUT zadania + Rozmowy

Zadanie
zadana tablica, przesuwajace sie okno i znalezc liczbe niepowtarzalnych elementow

#include<stdio.h>

void checkit(int t[],int s,int w)
{
   if(w>s)
   {
       printf("okno wieksze niz rozmiar tablicy");
       return;
   }

   int maxwindowindex=s-w;
   int licz=0;
   int difflicz=0;
   int localdiff=0;

   for(int i=0;i<=maxwindowindex;i++)    //loop for moving "window"
   {
       difflicz=0;

       for(int k=0;k<w;k++)            //loop changing the checked item
       {
           licz=w;
           for(int j=0;j<w;j++)       //loop comparing the checked element with other elements of the window
           {
                licz--;
                if(t[i+k] != t[i+licz] )
                {
                    localdiff++;
                }

           }
           if(localdiff==(w-1))
           {
               difflicz++;
           }
           localdiff=0;
       }

       printf("w okienku nr %d mamy %d niepowtarzalne elementy \n",i+1,difflicz);
       printf("\n");
   }
    return;
}



int main()
{
    int tab[]={1,2,3,4,5,5,7,8,9,10};

    int size=sizeof(tab)/(sizeof(int));

    int window=3;

printf("\nwielkosc twojej tablicy to %d, rozmiar okna to %d \n",size, window);
printf("w takiej konfiguracji masz %d roznych polozen okna\n\n",size-window+1);


checkit(tab,size,window);

    return 0;
}


Zadanie1

Inteligentny wskaźnik

Napisz swoją implementację wskaźnika:



bez licznika referencji

szablon

semantyka przenoszenia

operatory * -> == != < <= > >=

void swap(?, ?)

funkcja get()



z licznikiem referencji

szablon

kopiowanie + przenposzenie

blok kontrolny

brak weak_ptr

operatory * -> == != < <= > >=

void swap(?, ?)

funkcja get()



Zadanie 2:

Ring Buffer

Napisać implementację RingBuffer:

RingBuffer - potrafi przechowywać maksymalnie N elementów

https://en.wikipedia.org/wiki/Circular_buffer

RingBuffer ma być kontenerem STL


ma wspierać range for oraz podstawowe algorytmy STL'a





Zadanie3:

Matrix<M,N,T>

Napisać implementację:

posiada operatory:

dodawania macierzy (+)

mnożenia macierzy (+)

dodawania skalara do macierzy (+)

mnożenia macierzy przez skalar (+)

dostarcza konstruktory:

domyślny

kopiujący (+)

przesuwający*



Zadanie dodatkowe: gdzie występuje (+) implementacja ma działać dla typu T1 który jest konwertowalny do typu T





Rozwiązania GIT

https://github.com/JanosikOpryszek/kod/tree/master/ZUT/zadania






zadanie 1



#include <iostream>
#include <vector>

using namespace std;

// smart wskaznik bez licznika referencji - wskaznik wylaczny jak unique_ptr
template <typename T>
class Unique
{
    public:
    Unique(){                       // konstruktor bezparametrowy
        pointer = nullptr;
    }
    Unique(T* ptr){                 // konstruktor z parametrem
        pointer = ptr;
    }

    ~Unique(){                     //destruktor
        delete pointer;
    }

    T* get(){                 //funkcja get
        return pointer;
    }

    void swap(Unique& other){      //funkcja swap
        T* tmp = pointer;
        pointer = other.pointer;
        other.pointer = tmp;
    }

    Unique(Unique&& other){                //konstruktor przenoszacy
        T* tmp = pointer;
        pointer = other.pointer;
        other.pointer = nullptr;
    }


    T operator * (){      // operator *
     if(pointer)
        return *(pointer);
     else
        return 0;
    }

    bool operator==(const Unique& other){     // operator ==
     if(pointer && other.pointer )
     {
         if(*pointer  == *other.pointer)
            return true;
         else
            return false;
     }
     else
        return 0;
    }


    bool operator != (const Unique& other){      // operator !=
    if(pointer && other.pointer )
    {
         if(*pointer  != *other.pointer)
            return true;
         else
            return false;
    }
    else
        return 0;
    }


    bool operator < (const Unique& other){      // operator <
    if(pointer && other.pointer )
    {
        if(*pointer  < *other.pointer)
            return true;
         else
            return false;
     }
     else
        return 0;
    }


    bool operator <= (const Unique& other){      // operator <=
    if(pointer && other.pointer )
    {
        if(*pointer  <= *other.pointer)
            return true;
         else
            return false;
     }
     else
        return 0;
    }


    bool operator > (const Unique& other){      // operator >
    if(pointer && other.pointer )
    {
        if(*pointer  > *other.pointer)
            return true;
         else
            return false;
     }
     else
        return 0;
    }


    bool operator >= (const Unique& other){      // operator >=
    if(pointer && other.pointer )
    {
        if(*pointer  >= *other.pointer)
            return true;
         else
            return false;
     }
     else
        return 0;
    }


    private:                             //prywatny, blokowanie uzycia konst. kopiujacego i operatora przypisania
    Unique(const Unique& other) {};               // kopiujacy
    Unique& operator=(const Unique& other){}      // operator  przypisania
    T* pointer;

};

//**********************************************************************************

// smart wskaznik z licznikiem referencji - wskaznik wspoldzielony jak shared_ptr
template <typename T>
class Shared
{
    public:



    Shared(T* ptr): pointer(ptr),licznik(new int){                 // konstruktor z parametrem
        *licznik=1;
    }

    Shared(const Shared<T>& other) {        // konstruktor kopiujacy
    licznik=other.licznik;
    pointer=other.pointer;
    (*licznik)++;
    }



    Shared(Shared&& other){              //konstruktor przenoszacy
        pointer = other.pointer;
        licznik=other.licznik;
        delete other;            // albo pointer i licznik
    }


    ~Shared(){                     //destruktor
        if(*licznik>1)
            {
                (*licznik)--;
            }
        else if (*licznik==1)
        {
            delete pointer;
            delete licznik;
        }
     }


    T* get(){                 //funkcja get
        return pointer;
    }

    void swap(Shared& other){      //funkcja swap
        T* tmp = pointer;
        pointer = other.pointer;
        other.pointer = tmp;
        int* tmp2 = licznik;
        licznik = other.licznik;
        other.licznik = tmp2;


    }

    int ile(){               //funkcja ile
        return *licznik;
    }


    void operator=(const Shared<T>& other){      // operator  przypisania z innego wskaznika
        cout << "operator przypisania\n";
        if(pointer)
            {
                *pointer = *other.pointer;
                licznik=other.licznik;
                *licznik++;
            }
        else
            {
                pointer=new T;
                *pointer=*other.pointer;
                licznik=other.licznik;
                *licznik++;
            }
        }


    void reset(int wartosc){      // funkcja  przypisania wartosci
            *pointer = wartosc;
    }


    T operator * (){      // operator *
     if(pointer)
        return *(pointer);
     else
        return 0;
    }

    bool operator==(const Shared& other){     // operator ==
     if(pointer && other.pointer )
     {
         if(*pointer  == *other.pointer)
            return true;
         else
            return false;
     }
     else
        return 0;
    }


    bool operator != (const Shared& other){      // operator !=
    if(pointer && other.pointer )
    {
         if(*pointer  != *other.pointer)
            return true;
         else
            return false;
    }
    else
        return 0;
    }


    bool operator < (const Shared& other){      // operator <
    if(pointer && other.pointer )
    {
        if(*pointer  < *other.pointer)
            return true;
         else
            return false;
     }
     else
        return 0;
    }


    bool operator <= (const Shared& other){      // operator <=
    if(pointer && other.pointer )
    {
        if(*pointer  <= *other.pointer)
            return true;
         else
            return false;
     }
     else
        return 0;
    }


    bool operator > (const Shared& other){      // operator >
    if(pointer && other.pointer )
    {
        if(*pointer  > *other.pointer)
            return true;
         else
            return false;
     }
     else
        return 0;
    }


    bool operator >= (const Shared& other){      // operator >=
    if(pointer && other.pointer )
    {
        if(*pointer  >= *other.pointer)
            return true;
         else
            return false;
     }
     else
        return 0;
    }



    private:
    T* pointer;
    int* licznik;

};



void foo(Unique<int> argu){
    cout << "------------------z wnetrza funkcji to co dal przeslany argument: "<<*argu << endl;
}

Unique<int> foo2(Unique<int> argu){
    cout << "------------------z wnetrza funkcji to co dal przeslany argument: "<<*argu << endl;
    return move(argu);
}

void foos(Shared<int> argu){
    cout << "------------------z wnetrza funkcji, kopia argumentu  ma wartosc: "<<*argu << endl;
    cout << "------------------z wnetrza funkcji ile= "<< argu.ile()<< endl;;

}

int main()
{
        cout << "****************************************************************************************\n";
        cout << "Klasa Unique - smart wskaznik bez licznika referencji - wskaznik wylaczny jak unique_ptr \n";
        cout << "tworze wskaznik 'c' z wartoscia 10\n";
        Unique<int> c(new int(10));
        cout << "tworze wskaznik 'inny' z wartoscia 100\n";
        Unique<int> inny(new int(100));
        cout << "\n";
        cout <<"c.get() wyswietla adres: ";
        cout << c.get() << "\n";
        cout <<"*(c.get()) wyswietla wartosc: ";
        cout << *(c.get()) << "\n";
        cout <<"przeciazony *c wyswietla wartosc: ";
        cout << *c << "\n";
        cout << "\n";

        cout << "zamieniam 'inny' z 'c' za pomoca  inny.swap(c) \n";
        inny.swap(c);
        cout << "inny.get() wyswietla : ";
        cout << inny.get() << "\n";
        cout <<"*inny wyswietla: ";
        cout << *inny << "\n";
        cout <<"c.get() wyswietla: ";
        cout << c.get() << "\n";
        cout <<"*c wyswietla: ";
        cout << *c << "\n";
        cout << "\n";

        cout << "tworze nowy 'cc' konstruktorem przenoszacym z 'inny' cc(move(inny)), 'inny' powinien sie wyzerowac, 'cc' byc jak 'inny'\n";
        Unique<int> cc(move(inny));
        cout << "inny.get() wyswietla : ";
        cout << inny.get() << "\n";
        cout << "*inny wyswietla : ";
        cout << *inny << "\n";
        cout <<"cc.get() wyswietla: ";
        cout << cc.get() << "\n";
        cout <<"*cc wyswietla: ";
        cout << *cc << "\n";
        cout << "\n";

        //foo(c);  nie zadziala bo kopiujacy w obszarze prywatnym
        cout << "funkcja foo, pointer 'c' jako argument funkcji - przeslany konstruktorem przenoszacym foo(move(c))\n";
        foo(move(c));
        cout << "*c po przeniesieniu do argumentu funkcji wyswietla : ";
        cout << *c << "\n\n";
        cout << "funkcja foo2 ktora przyjmuje argument 'cc' i zwraca do 'odb' za pomoca konstruktora przenoszacego \n";
        Unique<int> odb( foo2(move(cc)) );
        cout <<"*cc wyswietla: ";
        cout << *cc << "\n";
        cout <<"*odb wyswietla: ";
        cout << *odb << "\n";
        cout << "\n";


        cout << "operator == \n";
        cout << "tworze wskaznika 'a' z wartoscia 5\n";
        Unique<int> a(new int(5));
        cout << "tworze wskaznika 'b' z wartoscia 5\n";
        Unique<int> b(new int(5));
        cout << "a == b  : ";
        if (a == b)
            cout << "rowne\n";
        else
            cout << "rozne\n";
        cout << "\n";

        cout << "operator != \n";
        cout << "a != b  : ";
        if (a != b)
            cout << "rozne\n";
        else
            cout << "nie rozne\n";
        cout << "\n";

        cout << "operator < \n";
        cout << "a < cc  : ";
        if (a != cc)
            cout << "prawda\n";
        else
            cout << "falsz\n";
        cout << "\n";

        cout << "*********************************************************************************************\n";
        cout << "Klasa Shared - smart wskaznik z licznikiem referencji - wskaznik wspoldzielony jak shared_ptr \n";
        cout << "tworze wskaznik 's' z wartoscia 7\n";
        Shared<int> s(new int(7));
        cout << "ile obiektow typu s : " << s.ile() << endl;
        cout << "\n";
        cout << "tworze wskaznik 's2' z wartoscia 10\n";
        Shared<int> s2(new int(10));
        cout << "ile obiektow  typu s : " << s2.ile() << endl;
        cout << "przypisanie do powyzszego wskaznika 's2' wartosci 11 za pomoca s2.reset(11) \n";
        s2.reset(11);
        cout << "*s2=" << *s2 <<"\n";
        cout << "ile obiektow  typu s2: " << s2.ile() << endl;
        cout << "\n";
        cout << "wywolanie funkcji foos(s2) czyli stworzenie kopi przez przeslanie argumentu\n";
        foos(s2);
        cout << "po wyjsciu z funkcji: ";
        cout << "ile obiektow typu s2 : " << s2.ile() << endl;
        cout << "\n";
        cout << "vector typu Shared<int> i dodane typu <int>\n";
        // umiesc wskazniki w kontenerze
        vector<Shared<int>> whoMadeCoffee;
        cout <<"zaczynam pushback\n";
        whoMadeCoffee.push_back(s);
        cout << "byl push s\n";
        whoMadeCoffee.push_back(s);
        cout << "byl push s\n";
        whoMadeCoffee.push_back(s2);
        cout << "byl push s2\n";
        whoMadeCoffee.push_back(s);
        cout << "byl push s\n";
        whoMadeCoffee.push_back(s2);
        cout << "byl push s2\n\n";
        cout << "wyswietlam rangefor:\n";
        // wypisz wszystkie elementy
        for (auto &ptr : whoMadeCoffee) {
             cout << *ptr << " ";
        }
        cout << "\nrangefor koniec\n";
        cout << endl ;
        cout << "ile obiektow s : " << s.ile() << endl;
        cout << "ile obiektow vector[s] : " << whoMadeCoffee[1].ile() << endl;
        cout << "\n";
        cout << "ile obiektow vector[s2] : " << whoMadeCoffee[2].ile() << endl;
        cout << "\n";
        cout << "tworze wskaznik 'ch' typu <char> z wartoscia 8\n";
        Shared<char> ch(new char(7));
        cout << "ile obiektow typu ch: " << ch.ile() << endl;
        cout << "ile obiektow typu s2 : " << s2.ile() << endl;


    return 0;
}
.
wynik:
****************************************************************************************
Klasa Unique - smart wskaznik bez licznika referencji - wskaznik wylaczny jak unique_ptr
tworze wskaznik 'c' z wartoscia 10
tworze wskaznik 'inny' z wartoscia 100

c.get() wyswietla adres: 0x7d1120
*(c.get()) wyswietla wartosc: 10
przeciazony *c wyswietla wartosc: 10

zamieniam 'inny' z 'c' za pomoca  inny.swap(c)
inny.get() wyswietla : 0x7d1120
*inny wyswietla: 10
c.get() wyswietla: 0x7d1190
*c wyswietla: 100

tworze nowy 'cc' konstruktorem przenoszacym z 'inny' cc(move(inny)), 'inny' powinien sie wyzerowac, 'cc' byc jak 'inny'
inny.get() wyswietla : 0
*inny wyswietla : 0
cc.get() wyswietla: 0x7d1120
*cc wyswietla: 10

funkcja foo, pointer 'c' jako argument funkcji - przeslany konstruktorem przenoszacym foo(move(c))
------------------z wnetrza funkcji to co dal przeslany argument: 100
*c po przeniesieniu do argumentu funkcji wyswietla : 0

funkcja foo2 ktora przyjmuje argument 'cc' i zwraca do 'odb' za pomoca konstruktora przenoszacego
------------------z wnetrza funkcji to co dal przeslany argument: 10
*cc wyswietla: 0
*odb wyswietla: 10

operator ==
tworze wskaznika 'a' z wartoscia 5
tworze wskaznika 'b' z wartoscia 5
a == b  : rowne

operator !=
a != b  : nie rozne

operator <
a < cc  : falsz

*********************************************************************************************
Klasa Shared - smart wskaznik z licznikiem referencji - wskaznik wspoldzielony jak shared_ptr
tworze wskaznik 's' z wartoscia 7
ile obiektow typu s : 1

tworze wskaznik 's2' z wartoscia 10
ile obiektow  typu s : 1
przypisanie do powyzszego wskaznika 's2' wartosci 11 za pomoca s2.reset(11)
*s2=11
ile obiektow  typu s2: 1

wywolanie funkcji foos(s2) czyli stworzenie kopi przez przeslanie argumentu
------------------z wnetrza funkcji, kopia argumentu  ma wartosc: 11
------------------z wnetrza funkcji ile= 2
po wyjsciu z funkcji: ile obiektow typu s2 : 1

vector typu Shared<int> i dodane typu <int>
zaczynam pushback
byl push s
byl push s
byl push s2
byl push s
byl push s2

wyswietlam rangefor:
7 7 11 7 11
rangefor koniec

ile obiektow s : 4
ile obiektow vector[s] : 4

ile obiektow vector[s2] : 3

tworze wskaznik 'ch' typu <char> z wartoscia 8
ile obiektow typu ch: 1
ile obiektow typu s2 : 3



                                    zad 2

Ring Buffer
Napisać implementację RingBuffer:
RingBuffer - potrafi przechowywać maksymalnie N elementów
https://en.wikipedia.org/wiki/Circular_buffer
RingBuffer ma być kontenerem STL
ma wspierać range for oraz podstawowe algorytmy STL'a



#include<iostream>
#include<vector>
#include<algorithm>
#include<string>

using namespace std;

template<typename T,int N>
class Ringbuffer
{

typename std::vector<T>::iterator it;
int licz=0;

public:

std::vector<T> myvec;

Ringbuffer()
{
    myvec.assign(N,0);
    it=myvec.begin();
}

typename std::vector<T>::iterator begin()
{
    return myvec.begin();
}

typename std::vector<T>::iterator end()
{
    myvec.end();

}

void push(T arg1 )
{
    if(licz==N)
    {
        std::rotate(myvec.begin(), myvec.begin() + 1, myvec.end());
        licz-=1;
    }
    *(it+licz)=arg1;
    licz+=1;
}


T pop()
{
    if (licz==0)
        return 0;
    T ret=*(it);
    std::rotate(myvec.begin(), myvec.begin() + 1, myvec.end());
    licz-=1;
    *(it+N-1)=0;
    return ret;
}

void show()
{
    for (auto element : myvec)
        cout<<element<<",";
    cout<<endl;
}

};



int main ()
{
cout << "tworze Ringbuffer typu int o wielkosci 10\n";
Ringbuffer<int,10> ring;

cout << "pushuje kolejno 10,11,12,13,14,15\n";
ring.push(10);
ring.push(11);
ring.push(12);
ring.push(13);
ring.push(14);
ring.push(15);

cout << "rangefor na vektorze z ringu: ";  //prawdziwy rangefor na koncu
for (auto element : ring.myvec)
    cout<<element<<",";
cout<<endl;

cout << "metoda show :";
ring.show();

cout << " pushuje 16,17,18\n";
ring.push(16);
ring.push(17);
ring.push(18);

cout << "metoda show :";
ring.show();

cout << " pushuje 19\n";
ring.push(19);

cout << "metoda show :";
ring.show();

cout << " pushuje 20\n";
ring.push(20);

cout << "metoda show :";
ring.show();

cout << " pushuje 21\n";
ring.push(21);

cout << "metoda show :";
ring.show();


cout<<"metoda pop\n"<<ring.pop()<<endl;

cout << "metoda show :";
ring.show();

cout<<"metoda pop\n"<<ring.pop()<<endl;

cout << "metoda show :";
ring.show();


cout << " pushuje 96,97,98\n";
ring.push(96);
ring.push(97);
ring.push(98);

cout << "metoda show :";
ring.show();

cout<<"metoda pop\n"<<ring.pop()<<endl;

cout << "metoda show :";
ring.show();
cout<<"metoda pop\n"<<ring.pop()<<endl;

cout << "metoda show :";
ring.show();
cout<<"metoda pop\n"<<ring.pop()<<endl;
cout<<"metoda pop\n"<<ring.pop()<<endl;

cout << "metoda show :";
ring.show();
cout<<"metoda pop\n"<<ring.pop()<<endl;
cout<<"metoda pop\n"<<ring.pop()<<endl;
cout<<"metoda pop\n"<<ring.pop()<<endl;
cout<<"metoda pop\n"<<ring.pop()<<endl;
cout<<"metoda pop\n"<<ring.pop()<<endl;
cout<<"metoda pop\n"<<ring.pop()<<endl;
cout<<"metoda pop\n"<<ring.pop()<<endl;

cout << "metoda show :";
ring.show();

cout << " pushuje 80,81,82,83,94,85\n";
ring.push(80);
ring.push(81);
ring.push(82);
ring.push(83);
ring.push(84);
ring.push(85);

cout << "metoda show :";
ring.show();

cout << " pushuje 86,87,88,89,90,91\n";
ring.push(86);
ring.push(87);
ring.push(88);
ring.push(89);
ring.push(90);
ring.push(91);

cout << "metoda show :";
ring.show();

cout<<"metoda pop\n"<<ring.pop()<<endl;
cout<<"metoda pop\n"<<ring.pop()<<endl;

cout << "metoda show :";
ring.show();

cout << "_____________range_for______________\n";
for (const auto& element: ring)
    cout<<element<<",";
cout<<endl;
cout << "_____________range_for______________\n";

return 0;
}


wynik programu:

tworze Ringbuffer typu int o wielkosci 10
pushuje kolejno 10,11,12,13,14,15
rangefor na vektorze z ringu: 10,11,12,13,14,15,0,0,0,0,
metoda show :10,11,12,13,14,15,0,0,0,0,
 pushuje 16,17,18
metoda show :10,11,12,13,14,15,16,17,18,0,
 pushuje 19
metoda show :10,11,12,13,14,15,16,17,18,19,
 pushuje 20
metoda show :11,12,13,14,15,16,17,18,19,20,
 pushuje 21
metoda show :12,13,14,15,16,17,18,19,20,21,
metoda pop
12
metoda show :13,14,15,16,17,18,19,20,21,0,
metoda pop
13
metoda show :14,15,16,17,18,19,20,21,0,0,
 pushuje 96,97,98
metoda show :15,16,17,18,19,20,21,96,97,98,
metoda pop
15
metoda show :16,17,18,19,20,21,96,97,98,0,
metoda pop
16
metoda show :17,18,19,20,21,96,97,98,0,0,
metoda pop
17
metoda pop
18
metoda show :19,20,21,96,97,98,0,0,0,0,
metoda pop
19
metoda pop
20
metoda pop
21
metoda pop
96
metoda pop
97
metoda pop
98
metoda pop
0
metoda show :0,0,0,0,0,0,0,0,0,0,
 pushuje 80,81,82,83,94,85
metoda show :80,81,82,83,84,85,0,0,0,0,
 pushuje 86,87,88,89,90,91
metoda show :82,83,84,85,86,87,88,89,90,91,
metoda pop
82
metoda pop
83
metoda show :84,85,86,87,88,89,90,91,0,0,
_____________range_for______________
84,85,86,87,88,89,90,91,0,0,
_____________range_for______________


                                    zad 3

Matrix<M,N,T>
Napisać implementację:
posiada operatory:
dodawania macierzy (+)
mnożenia macierzy (+)
dodawania skalara do macierzy (+)
mnożenia macierzy przez skalar (+)
dostarcza konstruktory:
domyślny
kopiujący (+)
przesuwający*

Zadanie dodatkowe: gdzie występuje (+) implementacja ma działać dla typu T1 który jest konwertowalny do typu T

#include<iostream>
#include<vector>
using namespace std;


template <int N,int M,typename T>
struct Matrix
{
std::vector<vector<T> > matryca {N,vector<T>(M)};         //macierz Vektorow o wielkosci NxM wypelniona zerami
std::vector<typename vector<T>::iterator> iteratory;      //vektor przechowujacy iteratory typu vector<T>
typename vector<vector<T> >::iterator it=matryca.begin(); //iterator 1 wymiaru macierzy, vektor na vektor


Matrix(){                                                 //konstruktor wypwlniajacy vektor iteratorw 2 wymiaru
if(N==0 && M==0)
    cout<<"N=0 i M=0, nie moge stworzyc"<<endl;
else
 for(int i=0;i<N;i++)
     iteratory.push_back((*(it+i)).begin());
}


template <int N1,int M1,typename T1>
Matrix (const Matrix<N1,M1,T1>& another){                        //konstruktor kopiujacy

if( std::is_convertible<T,T1>::value )
{
    if(N1<=N && M1<=M )
    {
        for(int i=0; i<N1;i++)
        {
            for( int j=0;j<M1;j++)
            {
            matryca[i][j]=another.matryca[i][j];
            }
        }
    }
    else
        cout<<"za duza tablica do skopiowania"<<endl;
}
else
    cout<<"niekonwertowalny TYP danych"<<endl;
}


template <int N1,int M1,typename T1>
Matrix (Matrix<N1,M1,T1>&& another){                        //konstruktor przenoszacy

if( std::is_convertible<T,T1>::value )
{
    if(N1<=N && M1<=M )
    {
        for(int i=0; i<N1;i++)
        {
            for( int j=0;j<M1;j++)
            {
            matryca[i][j]=another.matryca[i][j];
            another.matryca[i][j]=0;
            }
        }
    }
    else
        cout<<"za duza tablica do skopiowania"<<endl;
}
else
    cout<<"niekonwertowalny TYP danych"<<endl;
}




template <int N1,int M1,typename T1>
void operator +(Matrix<N1,M1,T1> another)  //dodawanie macierzy
{

if( std::is_convertible<T,T1>::value )
{
    if(N1<=N && M1<=M )
    {
        for(int i=0; i<N1;i++)
        {
            for( int j=0;j<M1;j++)
            {
            matryca[i][j]+=another.matryca[i][j];
            }
        }
    }
    else
        cout<<"za duza tablica do dodania"<<endl;
}
else
    cout<<"niekonwertowalny TYP danych"<<endl;
}


template <typename T1>
void operator +(T1 another)          //dodawanie skalara do macierzy
{

if( std::is_convertible<T,T1>::value )
{
    for(int i=0; i<N;i++)
    {
        for( int j=0;j<M;j++)
        {
        matryca[i][j]+=another;
        }
    }
}
else
    cout<<"niekonwertowalny TYP danych"<<endl;
}



template <int N1,int M1,typename T1>
void operator *(Matrix<N1,M1,T1> another)  //Mnozenie macierzy
{

if( std::is_convertible<T,T1>::value )
{
    if(N1<=N && M1<=M )
    {
        for(int i=0; i<N1;i++)
        {
            for( int j=0;j<M1;j++)
            {
            matryca[i][j]*=another.matryca[i][j];
            }
        }
    }
    else
        cout<<"za duza tablica do dodania"<<endl;
}
else
    cout<<"niekonwertowalny TYP danych"<<endl;
}


template <typename T1>
void operator *(T1 another)          //Mnozenie skalara przez macierz
{

if( std::is_convertible<T,T1>::value )
{
    for(int i=0; i<N;i++)
    {
        for( int j=0;j<M;j++)
        {
        matryca[i][j]*=another;
        }
    }
}
else
    cout<<"niekonwertowalny TYP danych"<<endl;
}



T operator[] (int n){                  //przeciazony operator [],podajesz zbiorowy index zwraca wartosc
int rz=(int)(n/M);
int nr=n-(rz*M);
return *(iteratory[rz]+nr);
}


friend ostream& operator<< (ostream& out, const Matrix& obj) {              //przeciazony operator <<
out<<"start---------"<<endl;
out<<"Twoja matryca: "<<endl;

for(int i=0; i<N;i++)
{
    for( int j=0;j<M;j++)
    {
      out<<obj.matryca[i][j];
      out<<",";
    }
out<<endl;
}
out<<"end-----------"<<endl;
return out;
}

};




int main()
{
cout<<endl<<"Implementacja Matrix<N, M, T>  gdzie N i M wielkosc, T - typ"<<endl<<endl;
cout<<"Stworzenie Matrix<3,4,int> aaa i wypelnia danymi."<<endl<<endl;

Matrix<3,4,int> aaa;                                      //stworz macierz vektorw o wielkosci 3x3

aaa.matryca[0][0]=10;
aaa.matryca[0][1]=11;
aaa.matryca[0][2]=12;
aaa.matryca[0][3]=77;

aaa.matryca[1][0]=13;
aaa.matryca[1][1]=14;
aaa.matryca[1][2]=15;
aaa.matryca[1][3]=88;

aaa.matryca[2][0]=16;
aaa.matryca[2][1]=17;
aaa.matryca[2][2]=18;
aaa.matryca[2][3]=99;


cout<<"Polecenie: 'cout << aaa' przeciazony <<  wynik:"<<endl;    // operator <<
cout<<aaa<<endl;

cout<<"Polecenie: 'cout << aaa[4]' przeciazony(jeden index na cala macierz) []  wynik:"<<endl;        //operator []
cout<<(aaa[4])<<endl;;
cout<<"end-----------"<<endl<<endl;


cout<<"Stworzenie Matrix<4,5,int> bb(aaa) za pomoca konstruktora kopiujacego."<<endl<<endl;;
Matrix<4,5,double> bb(aaa);         //konstruktor kopiujacy (tylko do wiekszej)

cout<<"Stworzona konstruktorem kopiujacym bb wyglada tak:"<<endl;
cout<<bb<<endl<<endl;                     //wyswietl


cout<<"Stworzenie Matrix<4,5,int> cc(aaa) za pomoca konstruktora przenoszacego."<<endl<<endl;;
Matrix<4,5,double> cc(move(aaa));         //konstruktor kopiujacy (tylko do wiekszej)

cout<<"Stworzona konstruktorem przenoszacym cc wyglada tak:"<<endl;
cout<<cc<<endl<<endl;                     //wyswietl

cout<<"Po przeniesieniu aaa wyglada tak:"<<endl;
cout<<aaa<<endl<<endl;                     //wyswietl


cout<<"Dodaj bb+cc, przeciazony + , wynik zapisz w bb."<<endl<<endl;

bb+cc;

cout<<"Po dodaniu Twoje bb wyglada tak:"<<endl;
cout<<bb<<endl<<endl;                     //wyswietl


cout<<"Dodaj skalar 5 do bb, przeciazony + , wynik zapisz w bb."<<endl<<endl;

bb+5;

cout<<"Po dodaniu Twoje bb wyglada tak:"<<endl;
cout<<bb<<endl<<endl;                     //wyswietl


cout<<"przemnoz bb*cc, przeciazony * , wynik zapisz w bb."<<endl<<endl;

bb*cc;

cout<<"Po mnozeniu Twoje bb wyglada tak:"<<endl;
cout<<bb<<endl<<endl;                     //wyswietl


cout<<"przemnoz skalar 2 przez bb, przeciazony * , wynik zapisz w bb."<<endl<<endl;

bb*2;

cout<<"Po mnozeniu Twoje bb wyglada tak:"<<endl;
cout<<bb<<endl<<endl;                     //wyswietl


return 0;
}

wynik programu:

Implementacja Matrix<N, M, T>  gdzie N i M wielkosc, T - typ

Stworzenie Matrix<3,4,int> aaa i wypelnia danymi.

Polecenie: 'cout << aaa' przeciazony <<  wynik:
start---------
Twoja matryca:
10,11,12,77,
13,14,15,88,
16,17,18,99,
end-----------

Polecenie: 'cout << aaa[4]' przeciazony(jeden index na cala macierz) []  wynik:
13
end-----------

Stworzenie Matrix<4,5,int> bb(aaa) za pomoca konstruktora kopiujacego.

Stworzona konstruktorem kopiujacym bb wyglada tak:
start---------
Twoja matryca:
10,11,12,77,0,
13,14,15,88,0,
16,17,18,99,0,
0,0,0,0,0,
end-----------


Stworzenie Matrix<4,5,int> cc(aaa) za pomoca konstruktora przenoszacego.

Stworzona konstruktorem przenoszacym cc wyglada tak:
start---------
Twoja matryca:
10,11,12,77,0,
13,14,15,88,0,
16,17,18,99,0,
0,0,0,0,0,
end-----------


Po przeniesieniu aaa wyglada tak:
start---------
Twoja matryca:
0,0,0,0,
0,0,0,0,
0,0,0,0,
end-----------


Dodaj bb+cc, przeciazony + , wynik zapisz w bb.

Po dodaniu Twoje bb wyglada tak:
start---------
Twoja matryca:
20,22,24,154,0,
26,28,30,176,0,
32,34,36,198,0,
0,0,0,0,0,
end-----------


Dodaj skalar 5 do bb, przeciazony + , wynik zapisz w bb.

Po dodaniu Twoje bb wyglada tak:
start---------
Twoja matryca:
25,27,29,159,5,
31,33,35,181,5,
37,39,41,203,5,
5,5,5,5,5,
end-----------


przemnoz bb*cc, przeciazony * , wynik zapisz w bb.

Po mnozeniu Twoje bb wyglada tak:
start---------
Twoja matryca:
250,297,348,12243,0,
403,462,525,15928,0,
592,663,738,20097,0,
0,0,0,0,0,
end-----------


przemnoz skalar 2 przez bb, przeciazony * , wynik zapisz w bb.

Po mnozeniu Twoje bb wyglada tak:
start---------
Twoja matryca:
500,594,696,24486,0,
806,924,1050,31856,0,
1184,1326,1476,40194,0,
0,0,0,0,0,
end-----------



Uwagi:
1) Skrócony sposób tworzenia vektora vektorów

std::vector<vector<T> > matryca {N,vector<T>(M)};


2) Jeśli chcesz stworzyć iterator na vektor ale nieznanego typu <T> (tu iterator 1 wymiaru matrycy)
dodaj typename:

typename vector<vector<T> >::iterator it=matryca.begin();


 jesli chcesz stworzyć vektor iteratorow  (iterator dla  typu vektor<T> )

std::vector<typename vector<T>::iterator> iteratory;

stworzenie i przypisanie do tego vektora  iteratorów (dlatego.begin) wewnętrznych vektorów- 2 wymiar macierzy

w konstruktorze:
for(int i=0;i<N;i++)
     iteratory.push_back( (*(it+i)).begin() );


3) Konstruktor kopiujący musi zawierac swoj template

template <int N1,int M1,typename T1>
Matrix (const Matrix<N1,M1,T1>& another){ 


4) Przeciążony operator << ma taka konstrukcje

friend ostream& operator<< (ostream& out, const Matrix& obj)


5) Jeśli chcesz sprawdzić czy typy są konwertowalne

std::is_convertible<T,T1>::value



*********************