2015-04-04 1 views
0

У меня есть класс MyHashMap, и я хочу реализовать итератор, но по какой-то причине я не могу. У меня есть вектор, который занимает частную структуру как тип, просто отлично, но когда я пытаюсь определить его с помощью итератора в моем государственном секторе, он говорит, что HashEntry не объявлен. Вот мой класс.C++ Iterator в моем классе не принимает в моей структуре как тип

template<typename KeyType, typename ObjectType> 
class MyHashMap 
{ 
    public: 

/***********ITERATOR FUNCTIONS****************/ 

    typedef typename std::vector<HashEntry>::iterator iterator; 
    typedef typename std::vector<HashEntry>::const_iterator const_iterator; 

    iterator begin() { return array.begin(); } 

    const_iterator begin() const { return array.begin(); } 

    iterator end() { return array.end(); } 

    const_iterator end() const { return array.end(); } 

    private: 
    struct HashEntry 
    { 
     KeyType  element; 
     ObjectType mapped; 
     EntryType info; 

     HashEntry( const KeyType & e = KeyType{ }, 
        const ObjectType & m = ObjectType{ }, 
        EntryType i = EMPTY) 
        : element{ e }, mapped{ m }, info{ i } { } 

     HashEntry( KeyType && e, 
        ObjectType && m, 
        EntryType i = EMPTY) 
        : element{ std::move(e) }, mapped{ std::move(m) }, info{ i } { } 
    }; 

    vector<HashEntry> array; 
}; 

Я получаю эти ошибки, как

error: ‘HashEntry’ was not declared in this scope 
    typedef typename std::vector<HashEntry>::iterator iterator; 
          ^
error: template argument 1 is invalid 
    typedef typename std::vector<HashEntry>::iterator iterator; 
            ^
error: template argument 2 is invalid 
error: ‘HashEntry’ was not declared in this scope 
    typedef typename std::vector<HashEntry>::const_iterator const_iterator; 
          ^
error: template argument 1 is invalid 
    typedef typename std::vector<HashEntry>::const_iterator const_iterator; 
            ^
error: template argument 2 is invalid 

Любые идеи, что не так? Я уверен, что ответ прост, но я просто не могу понять. Заранее спасибо.

ответ

2

Это потому, что вы объявили HashEntryпосле Вы использовали его как параметр шаблона.

Это должно быть так:

template<typename KeyType, typename ObjectType> 
class MyHashMap 
{ 
    private: 
    struct HashEntry 
    { 
     KeyType  element; 
     ObjectType mapped; 
     EntryType info; 

     HashEntry( const KeyType & e = KeyType{ }, 
        const ObjectType & m = ObjectType{ }, 
        EntryType i = EMPTY) 
        : element{ e }, mapped{ m }, info{ i } { } 

     HashEntry( KeyType && e, 
        ObjectType && m, 
        EntryType i = EMPTY) 
        : element{ std::move(e) }, mapped{ std::move(m) }, info{ i } { } 
    }; 

    vector<HashEntry> array; 

    public: 
    /***********ITERATOR FUNCTIONS****************/ 

    //Now you can use 'HashEntry' as it is visible now: 

    typedef typename std::vector<HashEntry>::iterator iterator; 
    typedef typename std::vector<HashEntry>::const_iterator const_iterator; 

    iterator begin() { return array.begin(); } 

    const_iterator begin() const { return array.begin(); } 

    iterator end() { return array.end(); } 

    const_iterator end() const { return array.end(); } 
}; 

EDIT

Я думаю, что упреждающее объявление должно быть достаточно здесь, потому что, когда MyHashMap конкретизируется, HashEntry уже определен.

Но я думаю, что вы должны придерживаться одного, последовательного порядка декларирования вещей внутри классов (особенно шаблонных). я всегда делаю это следующим образом:

Например, это фрагмент из одного из моих пользовательских контейнеров: - внутренние типов и структур - базовые итераторы - общественные определения типов - члены - общедоступный интерфейс Затем, все всегда в нужном месте.

template <class T> 
class SortedArray 
{ 
protected: 
    class Block 
    { 
     //... 
    }; 

    class InternalCompare 
    { 
     //... 
    }; 

    template <IteratorType Iter_type> 
    class IteratorBase 
    { 
     //... 
    }; 

    template <IteratorType Iter_type> 
    class InternalIterator : public IteratorBase<Iter_type> 
    { 
     //... 
    }; 

    template <IteratorType Iter_type> 
    class InternalReverseIterator : public IteratorBase<Iter_type> 
    { 
     //... 
    }; 

public: 
    typedef SortedArray<T> MyType; 

    typedef InternalIterator<IteratorType::Non_Const>   Iterator; 
    typedef InternalIterator<IteratorType::Const>    ConstIterator; 
    typedef InternalReverseIterator<IteratorType::Non_Const> ReverseIterator; 
    typedef InternalReverseIterator<IteratorType::Const>  ConstReverseIterator; 


protected: 
    DynamicBuffer<Block> _blocks; 
    Size_t     _blocks_num; 
    Size_t     _elements_num; 
    Block*     _first_block; 
    Block*     _last_block; 

public: 
    SortedArray() 
    { 
     //... 
    }; 

    //etc. 
}; 

Но это всего лишь пример.

РЕДАКТИРОВАТЬ 2

Альтернативное решение, размещенных один является только вперед-объявить HashEntry. Это изменит только исходный код с одной дополнительной строки кода:

//This is your original code. 
template<typename KeyType, typename ObjectType> 
class MyHashMap 
{ 
private: 
    struct HashEntry; //This forward declaration is sufficient for everything to work properly. 

public: 
    /***********ITERATOR FUNCTIONS****************/ 
    typedef typename std::vector<HashEntry>::iterator iterator; 
    typedef typename std::vector<HashEntry>::const_iterator const_iterator; 

    iterator begin() { return array.begin(); } 

    const_iterator begin() const { return array.begin(); } 

    iterator end() { return array.end(); } 

    const_iterator end() const { return array.end(); } 

private: 
    struct HashEntry 
    { 
     KeyType  element; 
     ObjectType mapped; 
     EntryType info; 

     HashEntry( const KeyType & e = KeyType{ }, 
        const ObjectType & m = ObjectType{ }, 
        EntryType i = EMPTY) 
        : element{ e }, mapped{ m }, info{ i } { } 

     HashEntry( KeyType && e, 
        ObjectType && m, 
        EntryType i = EMPTY) 
        : element{ std::move(e) }, mapped{ std::move(m) }, info{ i } { } 
    }; 

    vector<HashEntry> array; 
}; 
+0

Я думаю, что здесь безопасно переслать объявить его, если вы хотите, как вы просто определить тип, и во время использования 'HashEntry' будет полностью определены. – vsoftco

+0

Спасибо, что сработали. Я не знал, что важно иметь место. – anonuser1234

+0

@vsoftco Да, здесь будет достаточно декларации. Я обновил свой ответ этой запиской, а также добавил небольшой пример схемы заказа, которую я лично использую. –

Смежные вопросы