Szablon klasy - lista struktur

0

Witam,

ostatnio zainteresowałem się szablonami i postanowiłem napisać własny pojemnik będący listą.
Dlaczego nie mogę utworzyć listy struktur zdefiniowanych przez siebie w funkcji main?

Oto mój kod:

lista.h

#ifndef LISTA_H
#define LISTA_H
#include <iostream>
#include <string>

template <typename T>
class Lista
{
public:
    Lista();
    void dodajNaKoniec(T dana);
    void dodajNaPoczatek(T dana);
    void wypisz();
    ~Lista();

private:
    struct TLista{
        T dana;
        TLista *poprzedni;
        TLista *nastepny;
    };

    TLista *pierwszy;
    TLista *ostatni;
};

#endif // LISTA_H

lista.cpp

#include "lista.h"


template <typename T>
Lista<T>::Lista() : pierwszy(0), ostatni(0)
{
}


template <typename T>
void Lista<T>::dodajNaPoczatek(T dana){
    TLista *e = new TLista;
    e->dana = dana;
    e->nastepny = 0;
    e->poprzedni = 0;

    if(pierwszy){
        pierwszy->poprzedni = e;
        e->nastepny = pierwszy;
        pierwszy = e;
    }
    else{
        pierwszy = e;
        ostatni = e;
    }
}


template <typename T>
void Lista<T>::dodajNaKoniec(T dana){
    TLista *e = new TLista;
    e->dana = dana;
    e->nastepny = 0;
    e->poprzedni = 0;

    if(ostatni){
        ostatni->nastepny = e;
        e->poprzedni = ostatni;
        ostatni = e;
    }
    else{
        pierwszy = e;
        ostatni = e;
    }
}


template <typename T>
void Lista<T>::wypisz(){
    TLista *temp;
    for(temp = pierwszy; temp != ostatni; temp = temp->nastepny)
        std::cout << temp->dana << ", ";
    std::cout << temp->dana << "\n";
}


template <typename T>
Lista<T>::~Lista(){

}

template class Lista<unsigned int>;
template class Lista<std::string>;

main.cpp

#include <iostream>
#include "lista.h"

struct osoba{
    std::string imie;
    std::string nazwisko;
};

int main()
{
    std::cout << "Lista unsigned intow:\n";

    Lista<unsigned int> l;
    l.dodajNaPoczatek(14);
    l.dodajNaPoczatek(25);
    l.dodajNaPoczatek(3);
    l.wypisz();

    std::cout << "\nLista stringow:\n";

    Lista<std::string> s;
    s.dodajNaKoniec("Grzegorz");
    s.dodajNaKoniec("Iksinski");
    s.dodajNaKoniec("Wroclaw");
    s.wypisz();

    std::cout << "\n";

    system("PAUSE");
}

Próbowałem jakoś dodać deklarację w pliku lista.cpp czyli coś w rodzaju:
'template class Listastd::string' ale zamiast std::string nie wiem co wstawić żeby było dobrze.

Plik lista.cpp nie wie nic o strukturze 'Osoba', a zadeklarowanie jej w pliku lista.h nic nie daje.

Nie mogę w pliku main.cpp zrobić takiego obiektu jak ten:
Lista<Osoba> os;

Bardzo proszę o jakąś podpowiedź.
Pozdrawiam
Grzegorz

0

Umiesc wszystkie definicje w pliku *.h

0

Znalazłem takie rozwiązanie w Internecie ale to nic nie daje właśnie.

lista.h

#ifndef LISTA_H
#define LISTA_H
#include <iostream>
#include <string>

template <typename T>
class Lista
{
public:
    Lista() : pierwszy(0), ostatni(0){}
    void dodajNaKoniec(T dana){
        TLista *e = new TLista;
        e->dana = dana;
        e->nastepny = 0;
        e->poprzedni = 0;

        if(ostatni){
            ostatni->nastepny = e;
            e->poprzedni = ostatni;
            ostatni = e;
        }
        else{
            pierwszy = e;
            ostatni = e;
        }
    }

    void dodajNaPoczatek(T dana){
        TLista *e = new TLista;
        e->dana = dana;
        e->nastepny = 0;
        e->poprzedni = 0;

        if(pierwszy){
            pierwszy->poprzedni = e;
            e->nastepny = pierwszy;
            pierwszy = e;
        }
        else{
            pierwszy = e;
            ostatni = e;
        }
    }

    void wypisz(){
        TLista *temp;
        for(temp = pierwszy; temp != ostatni; temp = temp->nastepny)
            std::cout << temp->dana << ", ";
        std::cout << temp->dana << "\n";
    }

    ~Lista();

private:
    struct TLista{
        T dana;
        TLista *poprzedni;
        TLista *nastepny;
    };

    TLista *pierwszy;
    TLista *ostatni;
};

#endif // LISTA_H

Nawet jak dodam do pliku 'lista.h' taką informację

template class Lista<unsigned int>;
template class Lista<std::string>;

To mam mnóstwo błędów typu undefined reference dla typów unsigned i string. Nie wiem co robię źle. Czytałem, że szablony STL są zrobione w całości w nagłówkach żeby można było tworzyć pojemniki każdego typu ale u mnie to nie działa.

Pozdrawiam
Grzegorz

0

Oto błędy kompilatora:

main.cpp:13: błąd:undefined reference to `Lista<unsigned int>::Lista()'
main.cpp:14: błąd:undefined reference to `Lista<unsigned int>::dodajNaPoczatek(unsigned int)'
main.cpp:15: błąd:undefined reference to `Lista<unsigned int>::dodajNaPoczatek(unsigned int)'
main.cpp:16: błąd:undefined reference to `Lista<unsigned int>::dodajNaPoczatek(unsigned int)'
main.cpp:17: błąd:undefined reference to `Lista<unsigned int>::wypisz()'
main.cpp:21: błąd:undefined reference to `Lista<std::string>::Lista()'
main.cpp:22: błąd:undefined reference to `Lista<std::string>::dodajNaKoniec(std::string)'
main.cpp:23: błąd:undefined reference to `Lista<std::string>::dodajNaKoniec(std::string)'
main.cpp:23: błąd:undefined reference to `Lista<std::string>::dodajNaKoniec(std::string)'
main.cpp:25: błąd:undefined reference to `Lista<std::string>::wypisz()'
main.cpp:21: błąd:undefined reference to `Lista<std::string>::~Lista()'
main.cpp:29: błąd:undefined reference to `Lista<unsigned int>::~Lista()'
main.cpp:21: błąd:undefined reference to `Lista<std::string>::~Lista()'
main.cpp:29: błąd:undefined reference to `Lista<unsigned int>::~Lista()'
collect2.exe:-1: błąd:error: ld returned 1 exit status

Krótko mówiąc kompilator nie widzi żadnej definicji z szablonu Lista mimo, że one tam są :)

0

Wrzuc loga z bledami bez tego czegos:

template class Lista<unsigned int>;
template class Lista<std::string>;
0

To jest log z błędami bez tego czegoś :)
Właśnie dlatego nie wiem o co chodzi.

0
  1. Dodaj implementacje destruktora jakakolwiek.
  2. Cos masz pochranione z configiem projektu, bo na ideone smiga: http://ideone.com/scf7mz
0

Dodałem destruktor - taki sam rezultat :-/

To jest konfig projektu - Qt Creator, kompilator minGW.

TEMPLATE = app
CONFIG += console
CONFIG -= app_bundle
CONFIG -= qt

SOURCES += main.cpp \
    lista.cpp

HEADERS += \
    lista.h
0

Usunąłem wpis odnośnie lista.cpp i błędów mam mniej, bo błędy są tylko odnośnie tworzenia obiektów typu unsigned i string.
Nawet jak dopiszę to co poniżej:

template class Lista<unsigned int>;
template class Lista<std::string>;

To kompilator sypie błędami typu Lista is not a class template, explicit instatiation of non-template type Lista.

1

Wszystkie pomysly juz wykorzystalem, jedyne moge dodac SOA#1 z nastepujacymi plikami:

main.cpp

#include <iostream>
#include "lista.h"
using namespace std;

int main()
{
    Lista<int> l;
    l.dodajNaKoniec(10);
    return 0;
}

lista.h

#ifndef LISTA_H
#define LISTA_H

#include <iostream>
#include <string>

template <typename T>
class Lista
{
public:
    Lista() : pierwszy(0), ostatni(0){}
    void dodajNaKoniec(T dana){
        TLista *e = new TLista;
        e->dana = dana;
        e->nastepny = 0;
        e->poprzedni = 0;

        if(ostatni){
            ostatni->nastepny = e;
            e->poprzedni = ostatni;
            ostatni = e;
        }
        else{
            pierwszy = e;
            ostatni = e;
        }
    }

    void dodajNaPoczatek(T dana){
        TLista *e = new TLista;
        e->dana = dana;
        e->nastepny = 0;
        e->poprzedni = 0;

        if(pierwszy){
            pierwszy->poprzedni = e;
            e->nastepny = pierwszy;
            pierwszy = e;
        }
        else{
            pierwszy = e;
            ostatni = e;
        }
    }

    void wypisz(){
        TLista *temp;
        for(temp = pierwszy; temp != ostatni; temp = temp->nastepny)
            std::cout << temp->dana << ", ";
        std::cout << temp->dana << "\n";
    }

    ~Lista() {}

private:
    struct TLista{
        T dana;
        TLista *poprzedni;
        TLista *nastepny;
    };

    TLista *pierwszy;
    TLista *ostatni;
};

#endif // LISTA_H

untitled.pro

TEMPLATE = app
CONFIG += console
CONFIG -= app_bundle
CONFIG -= qt

SOURCES += main.cpp

HEADERS += \
    lista.h

Hmm... czy na pewno instalacja Qt Ci odpowiednio dziala? W sensie kompiluja sie jakies przyklady?

0

Hehe słuchaj, działa :)

To teraz powiedz co zrobiłeś czego nie zrobiłem ja? Wyobraź sobie, że nawet z plikiem lista.cpp w projekcie to działa, tylko plik lista.cpp jest w całości zakomentowany w środku.

Popatrzyłem sobie i źródła nagłówka są takie jak ja miałem.

1

To samo ale w sposób kompaktowy:

#include <iostream>

template<typename T> class List
  {
   private:
   struct Item
     {
      T value;
      Item *prev,*next;
      Item(const T &value,Item *prev,Item *next):value(value),prev(prev),next(next) {}
     };
   Item *first,*last;
   public:
   List():first(0),last(0) {}
   //List(const List &L) //TODO
   //List &operator=(const List &L) //TODO
   void push_back(const T &value)
     {
      last=(last?last->next:first)=new Item(value,last,0);
     }
   void push_front(const T &value)
     {
      first=(first?first->prev:last)=new Item(value,0,first);
     }
   std::ostream &show(std::ostream &s)const
     {
      for(Item *i=first;i;i=i->next) s<<i->value<<", ";
      return s;
     }
   ~List()
     {
      while(first)
        {
         Item *tmp=first;
         first=first->next;
         delete tmp;
        }
     }
  };
template<typename T> inline std::ostream &operator<<(std::ostream &s,const List<T> &L)
  {
   return L.show(s);
  }

int main()
  {
   List<int> L;
   L.push_back(1);
   L.push_front(2);
   L.push_back(3);
   L.push_front(4);
   L.push_back(5);
   L.push_front(6);
   L.push_back(7);
   std::cout<<L<<std::endl;
   return 0;
  }

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