[C/C++] Stos jako template

0

Cześć.

Chciałem napisać sobie stos jako template i chyba prawie mi się udało oprócz tego, że gdy na stosie chce umieścić sobie string'a to niestety wywala mi błąd, może mi ktoś podpowiedzieć/powiedzieć dlaczego? Ponadto czy mógłby ktoś mi wyjaśnić różnicę między operatorem << jako funkcja składowa i jako funkcja zaprzyjaźniona?

#include <iostream>
#include<cstdlib>
//#include <string>
#define DEFAULT_INITIAL_SIZE_ 2



using namespace std;

template<class B>
class Stack{
   private:
      B*data;
      long size;   
      long top;    

   public:
      
      Stack();

      
      Stack(long size);


       
        ~Stack(){
      
            delete[] data;
        }

        void push(B element){
            if(this->top==this->size){
               
             
                    stack_resize();
                }
            this->data[this->top]=element;
            this->top++;

        }


       friend ostream& operator<<(ostream& os,const Stack & s){
            if(s.top==0) return os<<"Stack is empty - nothing to print";
                    else{
                        for(int i=0;i<s.top;i++){
                            os<<s.data[i]<<" ";
                        }
                        return os<<"\n";
                    }
       }

    int pop(){
        if(this->top==0){
            cout<<"Can't pop from empty stack"<<endl;
            exit(1);   
            }else{
                this->top--;
                return *(this->data+this->top);
                }
    }

    bool is_empty(){
        if(this->top==0) return true;
            else return false;

    }

    void clear(){
        this->top=0;
    }

    private:
        void stack_resize(){
            B*temporary_data=new B[2*(this->size)];
            for(int i=0;i<(this->size);i++){
               
                temporary_data[i]=(this->data[i]);
            }
           
            delete[] this->data;
            /
            this->data=temporary_data;
            this->size=2*(this->size);
        }

};
template<class B>
Stack<B>::Stack():size(2), top(0){
   /

   try{
      data=new B[2];
   }catch(bad_alloc& ex){
        cout<<ex.what()<<endl;
        //destruktor ???
    }
}

template<class B>
Stack<B>::Stack(long size){

       if(size<=0){
       
        data=new B[2];
        this->size=2;
        this->top=0;
       }
       else{
 
           try{
                this->size=size;
                this->top=0;
                data=new B[size];
            }catch(bad_alloc& ex){
                 cout<<ex.what()<<endl;
                //destruktor ???
            }
        }
}

Z góry dzięki.

2
  1. Jakie są błędy przy użyciu std::string?
  2. Pokaż przykład użycia twojej klasy.
  3. Dlaczego dla klasy szablonowej zwracasz na sztywno określony typ int pop() zamiast B (B też jest kiepskim wyborem (T))?
  4. Stos nie wypisuje swojej całej zawartości, więc operator<< jest niepotrzebny, klasa odkłada na stos i zwraca element przy zdejmowaniu plus dostęp do elementu na wierzchu przez metodę top.
  5. #define DEFAULT_INITIAL_SIZE_ 2 -> dlaczego nie constexpr std::size_t default_initial_size = 2u;.

Podejrzyj jak to wygląda: http://en.cppreference.com/w/cpp/container/stack.
Produkowanie klas, których zachowanie nie jest standardowe może być mylące dla konsumenta twoje klasy.

0

Przy stringu masz błąd w czasie kompilacji, tak? Zakładam, że to nie VS, bo on przepuszcza często takie rzeczy.
Poczytaj sobie to: http://en.cppreference.com/w/cpp/language/dependent_name
Ogólnie używając szblonów do instancjonowania innych szablonów wymaga w niektórych miejscach dyrektywy typename, żeby kompilator to ogarnął. A std::string jest szablonem.

0

Po przemyśleniu to chyba jednak nie to. I wygląda, że twój kod działa: https://ideone.com/rgq2DD
Chyba, że masz inny błąd?

0

Wywołaj metodę pop i dla szablonu ze stringiem objawi się błąd.

1

Aa to teraz oczywiste :)
zamień int pop() na B pop() i będzie działać: https://ideone.com/J1oz15

0

Haha, faktycznie nie zauważyłem tego :) Wieczorem spróbuję poprawić pop'a i dam znać czy wszystko już działa.

0

std::vector + reserve(rozmiarStosu) i masz w pełni funkcjonalny i optymalny stos.

0

Dobra, jak mam

Stack<string>my_string_stack;
string name1="Tomek";
	my_string_stack(name1);

to mam errora postaci:
[Error] no match for call to '(Stack<std::basic_string<char> >) (std::string&)'

1

my_string_stack(name1); - co tutaj robisz?
Nie można wywołać konstruktora dla już utworzonego obiektu.
Ba. Nawet nie masz konstruktora, który przyjmuje łańcuch znaków.

0

Ok wszystko już wiadomo - moje idiotyczne niedopatrzenie ale dziękuję wszystkim za pomoc :)

1 użytkowników online, w tym zalogowanych: 0, gości: 1