我有一个名为MyHashMap的类,我想实现一个迭代器,但出于某种原因,我无法做到。我有一个向量,它接受一个私有结构作为一种类型,但当我尝试在我的公共部门使用迭代器定义它时,它说没有声明HashEntry。这是我的班级。
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
任何想法有什么不对?我相当肯定答案很简单,但我无法弄明白。先感谢您。
答案 0 :(得分: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(); }
};
修改强>
我认为前向声明应该足够了,因为实例化MyHashMap
时,HashEntry
已经定义。
但是我认为,你应该坚持一致,在类中声明事物的顺序(特别是模板化的)。 我总是这样做:
例如,这是我的一个自定义容器的片段: - 内部类型和结构 - 基础迭代器 - 公共typedef - 成员 - 公共界面 然后,一切都在正确的地方。
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;
};