2015-03-17 2 views
1

Я начал писать свою собственную библиотеку с общими структурами данных только для образовательных целей (то есть: личная практика). Тем не менее, я столкнулся с несколькими проблемами, которые, по-моему, не могут решить сами по себе в одном связанном списке. Я не эксперт на C++, и, следовательно, у меня может возникнуть проблема с кодом, поэтому, пожалуйста, не стесняйтесь меня :)Ошибки Iterator C++ Custom List

Я попытался реализовать класс list_node, который объявляет и определяет узел для списка, list_iterator класс, который выступает в качестве передового итератора, который требуется для отдельного связанного списка, а также класс списка, который должен предоставить, использовать ранее упомянутые классы и предоставлять функциональность для списка.

Теперь я приложу код и ошибки, которые я получаю под Visual Studio.

list_node.h

/** 
* list_node.h 
* 
* @author Raul Butuc. 
* @version 1.0.0 16/03/2015 
*/ 

#pragma once 

#include "list.h" 
#include "list_iterator.h" 

namespace my_library { 

    template <class _Tp> 
    class list_node { 

    friend class list<_Tp>; 
    friend class list_iterator<_Tp>; 

    private: 
     _Tp m_Node; 
     list_node<_Tp> *m_pNext; 

     list_node(const _Tp&, list_node<_Tp>*); 
     ~list_node(); 
    }; 

    template <class _Tp> 
    list_node<_Tp>::list_node(const _Tp& node, list_node<_Tp>* next) : m_Node(node), m_pNext(next) {} 

    template <class _Tp> 
    list_node<_Tp>::~list_node() { 
    delete m_pNext; 
    } 

} 

list_iterator.h

/** 
* list_iterator.h 
* 
* @author Raul Butuc. 
* @version 1.0.0 16/03/2015 
*/ 

#pragma once 

#include <cassert> 
#include <iterator> 
#include "list.h" 
#include "list_node.h" 

namespace my_library { 

    template <class _Tp> class list; 
    template <class _Tp> class list_node; 

    template <class _Tp> 
    class list_iterator { 

    public: 
     // line below has error C2059: syntax error : '<' 
     // as well as error C2238: unexpected token(s) preceding ';' 
     friend class list<_Tp>; 
     typedef list_iterator<_Tp> iterator; 
     typedef size_t size_type; 
     typedef _Tp value_type; 
     typedef _Tp& reference; 
     typedef _Tp* pointer; 
     typedef std::forward_iterator_tag iterator_category; 
     typedef int difference_type; 

     const iterator& operator++(); 
     const iterator& operator++(int); 
     reference operator*(); 
     pointer operator->(); 
     bool operator==(const iterator&) const; 
     bool operator!=(const iterator&) const; 

    private: 
     list_node<_Tp>* m_pNode; 
     list_iterator(list_node<_Tp>*); 

    }; 

    template <class _Tp> 
    list_iterator<_Tp>::list_iterator(list_node<_Tp>* pNode) : m_pNode(pNode) {} 

    template <class _Tp> 
    const list_iterator<_Tp>::iterator& list_iterator<_Tp>::operator++() { 
    assert(m_pNode != NULL); 
    m_pNode = m_pNode->m_pNext; 
    return *this; 
    } 

    template <class _Tp> 
    const list_iterator<_Tp>::iterator& list_iterator<_Tp>::operator++(int) { 
    list_iterator<_Tp>::iterator _tmp = *this; 
    ++(*this); 
    return _tmp; 
    } 

    template <class _Tp> 
    list_iterator<_Tp>::reference list_iterator<_Tp>::operator*() { 
    return m_pNode->m_Node; 
    } 

    template <class _Tp> 
    list_iterator<_Tp>::pointer list_iterator<_Tp>::operator->() { 
    return m_pNode; 
    } 

    template <class _Tp> 
    bool list_iterator<_Tp>::operator==(const list_iterator<_Tp>::iterator& other) const { 
    return m_pNode == other->m_pNode; 
    } 

    template <class _Tp> 
    bool list_iterator<_Tp>::operator!=(const list_iterator<_Tp>::iterator& other) const { 
    return m_pNode != other->m_pNode; 
    } 

} 

list.h

/** 
* list.h 
* 
* @author Raul Butuc. 
* @version 1.0.0 16/03/2015 
*/ 

#pragma once 

#include "list_node.h" 
#include "list_iterator.h" 

namespace my_library { 

    template <class _Tp> 
    class list { 

    public: 
     typedef list_iterator<_Tp> iterator; 

     list(); 
     ~list(); 

     bool empty() const; 
     void push_back(const _Tp&); 

     iterator begin(); 
     iterator end(); 

    private: 
     list_node<_Tp>* m_pHead; 
     list_node<_Tp>* m_pTail; 
    }; 

    template <class _Tp> 
    list<_Tp>::list() : m_pHead(NULL), m_pTail(NULL) {} 

    template <class _Tp> 
    list<_Tp>::~list() { 
    delete m_pHead; 
    } 

    template <class _Tp> 
    bool list<_Tp>::empty() const { 
    return m_pHead == NULL; 
    } 

    template <class _Tp> 
    void list<_Tp>::push_back(const _Tp& node) { 
    list_node<_Tp>* _node = new list_node<_Tp>(node, NULL); 
    if (m_pHead == NULL) { 
     m_pHead = _node; 
    } 
    else { 
     m_pTail->m_pNext = _node; 
    } 
    m_pTail = _node; 
    } 

    template <class _Tp> 
    list<_Tp>::iterator list<_Tp>::begin() { 
    return list_iterator<_Tp>(m_pHead); 
    } 

    template <class _Tp> 
    list<_Tp>::iterator list<_Tp>::end() { 
    return list_iterator<_Tp>(NULL); 
    } 

} 

test.cpp

/** 
* Test.cpp 
* 
* @author Raul Butuc. 
* @version 1.0.0 16/03/2015 
*/ 

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

using std::cout; 
using namespace my_library; 

int main(int argc, char* argv[]) { 
    list<int> list; 

    if (list.empty()) { 
    std::cout << "List is empty" << "\n"; 
    } 

    for (int i = 0; i < 100; i += 10) { 
    list.push_back(i); 
    } 

    // Here it should allow me to write something like: 
    // list<int>::iterator it = list.begin(); 
    // However, it does not. Could someone please explain 
    // why that is so? Sorry if this is due to a naive mistake 
    // but I am trying to learn. Thanks again :) 
    list_iterator<int> it = list.begin(); 

    for (; it != list.end(); ++it) { 
    std::cout << *it << " "; 
    } 
    std::cout << "\n"; 

    system("pause"); 
    return 0; 
} 

Ошибки я получаю при компиляции

1>------ Build started: Project: List, Configuration: Debug Win32 ------
1> Test.cpp
1>d:...\list_iterator.h(23): error C2059: syntax error : '<'
1>\d:...\list_iterator.h(43) : see reference to class template instantiation 'my_library::list_iterator<_Tp>' being compiled
1>d:...\list_iterator.h(23): error C2238: unexpected token(s) preceding ';'
1>d:...\list_iterator.h(40): error C2143: syntax error : missing ';' before '<'
1>d:...\list_iterator.h(40): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1>d:...\list_iterator.h(40): error C2238: unexpected token(s) preceding ';'
1>d:...\list_iterator.h(41): error C2061: syntax error : identifier 'list_node'
1>d:...\list_iterator.h(46): error C2061: syntax error : identifier 'list_node'
1>d:...\list_iterator.h(49): warning C4346: 'my_library::list_iterator<_Tp>::iterator' : dependent name is not a type
1> prefix with 'typename' to indicate a type
1>d:...\list_iterator.h(49): error C2143: syntax error : missing ';' before '&'
1>d:...\list_iterator.h(49): error C2065: '_Tp' : undeclared identifier
1>d:...\list_iterator.h(49): error C2923: 'my_library::list_iterator' : '_Tp' is not a valid template type argument for parameter '_Tp'
1>d:...\list_iterator.h(53): error C2509: '++' : member function not declared in 'my_library::list_iterator'
1>
d:...\list_iterator.h(18) : see declaration of 'my_library::list_iterator'
1>d:...\list_iterator.h(53): fatal error C1903: unable to recover from previous error(s); stopping compilation
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

Большое спасибо, что нашли время!

EDIT:

Благодаря mebob, что было на самом деле главная проблема. Тем не менее, после фиксации, что я получаю некоторые ошибки в линии 52 и 56 в list_iterator.h:

1>d:\programming - data structures\list\list\list_iterator.h(52): warning C4346: 'my_library::list_iterator::iterator' : dependent name is not a type
1> prefix with 'typename' to indicate a type
1>d:\programming - data structures\list\list\list_iterator.h(52): error C2143: syntax error : missing ';' before '&'
1>d:\programming - data structures\list\list\list_iterator.h(52): error C2065: 'T' : undeclared identifier
1>d:\programming - data structures\list\list\list_iterator.h(52): error C2923: 'my_library::list_iterator' : 'T' is not a valid template type argument for parameter 'T'
1>d:\programming - data structures\list\list\list_iterator.h(56): error C2509: '++' : member function not declared in 'my_library::list_iterator'
1>
d:\programming - data structures\list\list\list_iterator.h(21) : see declaration of 'my_library::list_iterator'
1>d:\programming - data structures\list\list\list_iterator.h(56): fatal error C1903: unable to recover from previous error(s); stopping compilation

Я также изменил от _Tp Т во всех классах (в моем коде, не обновлять это здесь)

EDIT 2:

Даже после получения над этими ошибками, кажется, что он не будет компилировать, на этот раз из-операторов.

Код, который непосредственно участвует в:

// other code... 
    template <class _Tp> 
    typename list_iterator<_Tp>::pointer list_iterator<_Tp>::operator->() { 
    return m_pNode; 
    } 

    template <class _Tp> 
    bool list_iterator<_Tp>::operator==(const typename list_iterator<_Tp>::iterator& other) const { 
    /* error C2678: binary '->' : no operator found which takes a left-hand operand 
     of type 'const my_library::list_iterator<_Tp>' (or there is no acceptable conversion) */ 
    return m_pNode == other->m_pNode; 
    } 
    // other code... 

От list_iterator.h

+0

Было бы хорошо, если бы вы выделили первую строку, которая вызывает ошибку. –

+0

Извините за это, я не понял, что номера строк не включены. Дайте мне одну минуту. –

+1

Возможно, вы используете зарезервированный идентификатор http://stackoverflow.com/questions/228783/what-are-the-rules-about-using-an-underscore-in-ac-identifier –

ответ

1

Вы должны быть декларации вперед, например, так:

template <class _Tp> class list; 
template <class _Tp> class list_iterator; 

перед вашим другом деклараций, потому что в противном случае, когда компилятор видит friend class list, он не знает, что ожидает список аргументов шаблона.

Что касается вашей другой ошибки, вы должны использовать const typename list_iterator<_Tp>::iterator& для вашего типа. Каждый раз, когда вы ссылаетесь на тип, который является членом шаблонного класса (или структуры), вы должны заранее использовать ключевое слово typename, чтобы уточнить компилятору, что вы ожидаете его типа.

Ваша последняя ошибка просто потому, что вы пытаетесь вызвать неконстантный operator->() на const.Исправление состоит в том, чтобы просто создать версию const, которая возвращает указатель const.

Кроме того, как отметил Нил Кирк, _Tp, вероятно, является зарезервированным идентификатором, поэтому вы не должны его использовать.

+0

Спасибо! Я пробовал делать то же самое, но я написал его вот так: template Список классов <_Tp>;
Однако, я все еще получаю ошибки об этой линии (52) в list_iterator.h: Const list_iterator <_Tp> :: итератор и list_iterator <_Tp> :: оператор ++() { –

+1

@MasterKoder вы должны использовать 'Const имяТипа list_iterator <_Tp> :: итератор &' для вашего типа. Каждый раз, когда вы ссылаетесь на тип, который является членом шаблонизированного класса (или структуры), вы должны заранее использовать ключевое слово 'typename', чтобы уточнить компилятору, что вы ожидаете его типа. – chbaker0

+1

@MasterKoder, насколько мне известно, это связано с тем, что различные специализации могут определять определенное имя как тип в одном и значение в другом, но при анализе компилятор должен знать, что это такое. – chbaker0