Funkcja sprzątająca – program wyrzuca błędy i nie wiem jak je naprawić

0

Witam,

próbuję odpalić program, który omawia na swojej stronie Xion.
Przepisując kod co jakiś czas odpalam "Build and run" (codeblocks) żeby sprawdzić czy wszystko idzie dobrze.
Niestety w pewnym momencie kompilator wyrzucił mi następujący błąd:

||=== Build: Debug in Cleaner (compiler: GNU GCC Compiler) ===|
/home/michalzrb/workspace/Cleaner/main.cpp|34|error: need ‘typename’ before ‘Ptr<T>::Blocks:: iterator’ because ‘Ptr<T>::Blocks’ is a dependent scope|
/home/michalzrb/workspace/Cleaner/main.cpp|34|error: expected ‘;’ before ‘it’|
/home/michalzrb/workspace/Cleaner/main.cpp|37|error: ‘it’ was not declared in this scope|
/home/michalzrb/workspace/Cleaner/main.cpp|80|error: need ‘typename’ before ‘Ptr<T>::Blocks’ because ‘Ptr<T>’ is a dependent scope|
||=== Build failed: 4 error(s), 0 warning(s) (0 minute(s), 1 second(s)) ===|

poniżej dotychczasowy kod programu:

#include <iostream>
#include <map>


template <typename T> struct BlockInfo      ///dane o pojedynczym bloku pamięci
{
    const T* Ptr;
    int RefCount;

    explicit BlockInfo(T* ptr) : Ptr(ptr), RefCount(1) { }
};


template <typename T> class Ptr
{
    private:
        T* m_Ptr;       ///adres docelowego miejsca w pamięci

        ///typ kolekcji o zaalokowanych blokach

        typedef std::map<T*, BlockInfo<T>*> Blocks;

        ///rzeczona kolekcja
        static Blocks ms_Blocks;

        ///info o bloku pamięci na który aktualnie pokazuje wskaźnik
        BlockInfo<T>* m_pInfo;

        /// tworzy lub zwraca istnejącą strukturę BlockInfo na podstawie wskaźnika
        static BlockInfo<T>* GetBlockInfo(T* p)
        {
            //szukamy struktury w kolekcji
            BlockInfo<T>* pBI;
            Blocks::iterator it = ms_Blocks.find(p);

            //jeżeli nie znaleziono, tworzymy nową i dodajemy do kolekcji
            if(it == ms_Blocks.end())
                ms_Blocks.insert(std::make_pair(p, pBI = new BlockInfo<T>(p)));
            else
            {
                //w przeciwnym razie zwiększamy licznik znalezionego bloku
                pBI = it->second;
                ++pBI->RefCount;
            }
            return pBI;
        }

    public:
        ///konstruktor i destruktor
        Ptr(T* = 0);
        Ptr(const Ptr&);
        ~Ptr();

        //operatory przypisania
        T* operator = (T*);
        Ptr& operator = (const Ptr&);

        //operatory logiczne
        operator bool () const {return m_Ptr != 0;}
        bool operator ! () const {return !m_Ptr;}

        //operatory wskaźnikowe
        T& operator * () {return *m_Ptr;}
        const T& operator * () const {return *m_Ptr;}
        T* operator -> () {return m_Ptr;}

        //operatory konwersji na wskaźnik natywny
        operator T* () {return m_Ptr;}
        operator const T* () const {return m_Ptr;}


        ///zwraca akt. wartość licznika referencji
        int GetInfoCount() const {return m_pInfo ? m_pInfo->RefCount : 0;}

        ///pobranie licznika referencji
        int GetRefCount() const;

};

template <typename T> Ptr<T>::Blocks Ptr<T>::ms_Blocks;


using namespace std;

int main()
{

    return 0;
}

proszę o jakieś naprowadzenie na rozwiązanie

2
Blocks::iterator it = ms_Blocks.find(p);

need ‘typename’ before ‘Ptr<t>:: iterator’

dodaj typename albo użyj auto

0

Dzięki, ale następnie kompilator wskazuje na linię:

template <typename T> Ptr<T>::Blocks Ptr<T>::ms_Blocks;

/home/michalzrb/workspace/Cleaner/main.cpp|77|error: need ‘typename’ before ‘Ptr<T>::Blocks’ because ‘Ptr<T>’ is a dependent scope|<

dodam jeszcze, że źródło pochodzi z tej strony http://xion.org.pl/productions/texts/coding/simple-gc-in-cpp/

2

need ‘typename’ before ‘Ptr<t>::Blocks

template <typename T> Ptr<T>::Blocks Ptr<T>::ms_Blocks;
0

Dzięki, kompilator poszedł dalej, ale...

        static int Collect()
        {
            int Freed = 0;
            BlockInfo<T>* pBI;

            // przelatujemy po kolekcji zaalokowanych bloków tyle razy,
            // aż za którymś przebiegiem nie zwolnimy żadnego obiektu

            typename Blocks::iterator i;
            do
            {
                for(i = ms_Blocks.begin(); i != ms_Blocks.end(); ++i)
                {
                    //sprawdzamy czy licznik referencji osiągnął 0
                    if(!((pBI = i->second)->RefCount > 0))
                    {
                        if(pBI->Ptr) {delete pBI->Ptr; ++Freed;}

                        //usuwamy strukturę z informacjami o obiekcie
                        i = ms_Blocks.erase(i);        // **błąd w tej linii**
                        delete pBI;

                        //rozpoczynamy przeglądanie od początku
                        break;
                    }
                }
            } while (i != ms_Blocks.end());

            return Freed;
        }

wyrzuca błąd

/home/michalzrb/workspace/Cleaner/main.cpp|83|error: no match for ‘operator=’ (operand types are ‘std::map<int*, BlockInfo<int>, std::less<int>, std::allocator<std::pair<int* const, BlockInfo<int>> > >::iterator {aka std::_Rb_tree_iterator<std::pair<int const, BlockInfo<int>*> >}’ and ‘void’)|<

co rozumiem, jako próbę przypisania do iteratora wartości typu void
jak to naprawić ? sprawdzałem na stronie autora i kod się zgadza

1

Używasz jakiegoś antycznego kompilatora? Pre-c++11 map::erase zwracało void: https://en.cppreference.com/w/cpp/container/map/erase

0

Faktycznie, aktualizacja i pogrzebanie w opcjach kompilatora pomogło.
Program działa, dla:

Ptr <int> p;

ale już poniższy kod wyrzuca błąd

    int n;
    cout << "Input nuber of ints to allocate (pref. more than 10000)" << endl;
    cin >> n;
    cout << "Allocating..." << endl;
    Ptr p;                                  ///missing template arguments before 'p'
                                                                   
    for(int i = 0; i < n; ++i)
    {
        p = new int(i);
    }
    cout << "Allocated" << endl;
    cout << "Collecting..." << endl;
    cout << "Collected " << Collect() << " ints" << endl;
    return 0;
1

Szablonowi nadajesz typ w czasie kompilacji. Więc możesz mieć Ptr<int>, Ptr<string>, Ptr<double> itd., ale nie możesz wykorzystywać ich zamiennie.

0

Ok, ale założeniem (autora) funkcji Collect jest zwalnianie pamięci dla różnych typów. Czy w swoim kodzie coś pominął, przez co jego "Ptr p;" nie działa ?

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