Błąd kompilacji przy dziedziczeniu :public list<T>

0

Mam program jak poniżej (który przybrał taką formę aby jak najlepiej zilustrować mój problem)

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

class para
{
public:
    int dana;
    int ilosc;
    para(int wartosc, int ile=1):dana(wartosc), ilosc(ile){}
};


class wielozbior:public list<para>
{
public:
    ~wielozbior(){clear();}
    void dodaj(int d)
    {
        para *wsk= new para(d,12);
        push_back(*wsk);
    }

    void wypisz()
    {
        for(list<para>::const_iterator iter = begin(); iter!= end(); iter++)
            cout<<iter->dana<<" "<<iter->ilosc<<endl;
    }
};

/*
template <class T>
class probna:public list<T>
{
public:

    ~probna(){this->clear();} //dlaczego konieczne bylo dopisanie this-> ??

    void dodaj(T wartosc)
    {
        push_back(wartosc);
    }

    void wypisz()
    {
        for(list<T>::iterator iter=begin(); iter!=end(); iter++)   //dlaczego tutaj zwraca błąd
            cout<<*iter<<endl;
    }
};
*/

int main(void)
{
    wielozbior przyklad;
    przyklad.dodaj(5);
    przyklad.dodaj(2);
    przyklad.dodaj(3);
    przyklad.dodaj(1);

    przyklad.wypisz();

return 0;
}

Pomijam jakie było polecenie do zadania.
Moje pytanie brzmi "Dlaczego zwraca mi bląd w szablonie klasy probna (zakomentowane) przy probie utworzenia iteratora do odziedziczonego szablonu listy i jak obejsc ten problem?"

2
for(typename list<T>::iterator iter = this->begin() ; iter != this->end(); iter++)

http://stackoverflow.com/questions/17223446/dependent-scope-error-with-stl

2

for(list<T>::iterator iter=begin(); iter!=end(); iter++) //dlaczego tutaj zwraca błąd

Nie napisałeś jakiego używasz kompilatora, ale jeśli nim jest GCC, to przydałoby się czytać komunikaty.

borneo777.cpp:46:13: error: need 'typename' before 'std::__cxx11::list<T>::iterator' because 'std::__cxx11::list<T>' is a dependent scope
1

U mnie w VS 2013 Community wszystko się kompiluje bez errorów i warmingów.
A tak swoją drogą - nie lepiej używać typu auto? ;)

0

@Azarien a czy w takim razie:

  1. użycie w powyższym przykładzie for(list<para>::const_iterator iter = begin(); iter!= end(); iter++) jest prawidłowe (u mnie jak i zapewne u autora wątku również nie ma błędu)
  2. użycie auto iter = begin() - będzie prawidłowe?
  3. użycie zaproponowanego rozwiązania przez @Czarny Mleczarz tj. for(typename list<T>::iterator iter = this->begin() ; iter != this->end(); iter++) jest prawidłowe? oraz czy wpływa w jakiś sposób na wydajność iteracji/korzystania z vectorów/list etc?
    Z góry dzięki za rozwianie moich wątpliwości.
0

Dzięki Wam wielkie.
W odpowiedzi na jedno z pytań komplije GCC, komunikaty czytam i nawet je umiem przetłumaczyć ale programuje od niecalego roku i z typename się jeszcze nie spotakłem.

7
Księgowy napisał(a):
  1. użycie w powyższym przykładzie for(list<para>::const_iterator iter = begin(); iter!= end(); iter++) jest prawidłowe (u mnie jak i zapewne u autora wątku również nie ma błędu)

Jest poprawne gdy para to nie jest parametrem template. W przeciwnym wypadku mamy do czynienia z template dependent name i musimy wtedy poprzedzić go słowem typename. Podobnie odziedziczone po templatowej klasie składowe begin i end są nazwami zależnymi i musimy je poprzedzić this->.

 for (typename std::list<T> iter=this->begin(); iter!=this->end(); iter++) 
Księgowy napisał(a):
  1. użycie auto iter = begin() - będzie prawidłowe?

W przypadku klasy dziedziczącej po klasie szablonowej kontenera nie jest to prawidłowe, bo begin jest nazwą zależną. Rozwiązanie to this->begin().
Warto dodać, że bez podania this-> kompilator będzie szukał begin w innym (globalnym) lookup (będzie próbował wywołać std::begin() ale mu to się nie uda bo std::begin spodziewa się argumentu).

Księgowy napisał(a):
  1. użycie zaproponowanego rozwiązania przez @Czarny Mleczarz tj. for(typename list<T>::iterator iter = this->begin() ; iter != this->end(); iter++) jest prawidłowe? oraz czy wpływa w jakiś sposób na wydajność iteracji/korzystania z vectorów/list etc?

Prawidłowe i nie ma wpływu na wydajność kontenerów.

1

z typename się jeszcze nie spotakłem

A powinieneś, bo zalecane jest pisanie zawsze template <typename T> a nie template <class T>.

class T pisało się kiedyś, ale nowsze standardy przewidują w tym przypadku typename.

0

Używanie czegoś co nie jest już w użyciu jest niestety moją specjalnością.
PS Tak to bywa gdy się czyta Grębosza z 1996 bo nowszych wydań w bibliotece nie ma.

0

Czyli podsumowując, żeby rozwiać wszelkie wątpliwości, prawidłowo będzie tak:

for(auto iter = this->begin() ; iter != this->end(); iter++)

lub z typename:

for(typename list<T>::iterator iter = this->begin() ; iter != this->end(); iter++)

Tak?

Mam jeszcze wątpliwość odnośnie wydajności: czy dziedzicząc po vectorze/liście i korzystając z niego tak jak w powyższym przypadku nie powodujemy w jakiś sposób, że wpływa to na wydajność?

1

a czemu nikt nie wspomnial, ze nie powinien dziedziczyc publicznie po std::list?

Przeciez jezeli uzyje polimorfizmu to jego destruktor sie nie wykona bo kontenery stl nie maja wirtualnego destruktora

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