ENH: improve overall consistency of the HashTable and its iterators

- previously had a mismash of const/non-const attributes on iterators
  that were confused with the attributes of the object being accessed.

- use the iterator keys() and object() methods consistently for all
  internal access of the HashTable iterators. This makes the intention
  clearer, the code easier to maintain, and protects against any
  possible changes in the definition of the operators.

- 'operator*': The standard form expected by STL libraries.
  However, for the std::map, this dereferences to a <key,value> pair,
  whereas OpenFOAM dereferences simply to <value>.

- 'operator()': OpenFOAM treats this like the 'operator*'

- adjusted the values of end() and cend() to reinterpret from nullObject
  instead of returning a static iteratorEnd() object.
  This means that C++ templates can now correctly deduce and match
  the return types from begin() and end() consistently.
  So that range-based now works.

  Eg,
      HashTable<label> table1 = ...;
      for (auto i : table1)
      {
          Info<< i << endl;
      }

  Since the 'operator*' returns hash table values, this prints all the
  values in the table.
This commit is contained in:
Mark Olesen
2017-05-02 00:15:12 +02:00
parent 0298c02b2d
commit c0a50dc621
11 changed files with 331 additions and 364 deletions

View File

@ -177,6 +177,12 @@ int main()
Info<< "\ntable1" << table1 << nl; Info<< "\ntable1" << table1 << nl;
Info<< "\nrange-for(table1)" << nl;
for (auto const& it : table1)
{
Info<< " " << it << nl;
}
Info<< "\nDone\n"; Info<< "\nDone\n";
return 0; return 0;

View File

@ -45,7 +45,7 @@ Foam::HashPtrTable<T, Key, Hash>::HashPtrTable
{ {
for (const_iterator iter = ht.begin(); iter != ht.end(); ++iter) for (const_iterator iter = ht.begin(); iter != ht.end(); ++iter)
{ {
const T* ptr = *iter; const T* ptr = iter.object();
if (ptr) if (ptr)
{ {
this->insert(iter.key(), new T(*ptr)); this->insert(iter.key(), new T(*ptr));
@ -72,7 +72,7 @@ Foam::HashPtrTable<T, Key, Hash>::~HashPtrTable()
template<class T, class Key, class Hash> template<class T, class Key, class Hash>
T* Foam::HashPtrTable<T, Key, Hash>::remove(iterator& iter) T* Foam::HashPtrTable<T, Key, Hash>::remove(iterator& iter)
{ {
T* ptr = *iter; T* ptr = iter.object();
HashTable<T*, Key, Hash>::erase(iter); HashTable<T*, Key, Hash>::erase(iter);
return ptr; return ptr;
} }
@ -81,7 +81,7 @@ T* Foam::HashPtrTable<T, Key, Hash>::remove(iterator& iter)
template<class T, class Key, class Hash> template<class T, class Key, class Hash>
bool Foam::HashPtrTable<T, Key, Hash>::erase(iterator& iter) bool Foam::HashPtrTable<T, Key, Hash>::erase(iterator& iter)
{ {
T* ptr = *iter; T* ptr = iter.object();
if (HashTable<T*, Key, Hash>::erase(iter)) if (HashTable<T*, Key, Hash>::erase(iter))
{ {
@ -102,14 +102,9 @@ bool Foam::HashPtrTable<T, Key, Hash>::erase(iterator& iter)
template<class T, class Key, class Hash> template<class T, class Key, class Hash>
void Foam::HashPtrTable<T, Key, Hash>::clear() void Foam::HashPtrTable<T, Key, Hash>::clear()
{ {
for for (iterator iter = this->begin(); iter != this->end(); ++iter)
(
iterator iter = this->begin();
iter != this->end();
++iter
)
{ {
delete *iter; delete iter.object();
} }
HashTable<T*, Key, Hash>::clear(); HashTable<T*, Key, Hash>::clear();
@ -136,7 +131,7 @@ void Foam::HashPtrTable<T, Key, Hash>::operator=
for (const_iterator iter = rhs.begin(); iter != rhs.end(); ++iter) for (const_iterator iter = rhs.begin(); iter != rhs.end(); ++iter)
{ {
const T* ptr = *iter; const T* ptr = iter.object();
if (ptr) if (ptr)
{ {
this->insert(iter.key(), new T(*ptr)); this->insert(iter.key(), new T(*ptr));

View File

@ -54,7 +54,7 @@ template<class T, class Key, class Hash>
Istream& operator>>(Istream& is, HashPtrTable<T, Key, Hash>& L); Istream& operator>>(Istream& is, HashPtrTable<T, Key, Hash>& L);
template<class T, class Key, class Hash> template<class T, class Key, class Hash>
Ostream& operator<<(Ostream& os, const HashPtrTable<T, Key, Hash>& L); Ostream& operator<<(Ostream& os, const HashPtrTable<T, Key, Hash>& tbl);
/*---------------------------------------------------------------------------*\ /*---------------------------------------------------------------------------*\
@ -80,8 +80,8 @@ class HashPtrTable
public: public:
typedef typename HashTable<T*, Key, Hash>::iterator iterator; using iterator = typename HashTable<T*, Key, Hash>::iterator;
typedef typename HashTable<T*, Key, Hash>::const_iterator const_iterator; using const_iterator = typename HashTable<T*, Key, Hash>::const_iterator;
// Constructors // Constructors
@ -141,7 +141,7 @@ public:
friend Ostream& operator<< <T, Key, Hash> friend Ostream& operator<< <T, Key, Hash>
( (
Ostream& os, Ostream& os,
const HashPtrTable<T, Key, Hash>& L const HashPtrTable<T, Key, Hash>& tbl
); );
}; };

View File

@ -157,16 +157,9 @@ void Foam::HashPtrTable<T, Key, Hash>::read
template<class T, class Key, class Hash> template<class T, class Key, class Hash>
void Foam::HashPtrTable<T, Key, Hash>::write(Ostream& os) const void Foam::HashPtrTable<T, Key, Hash>::write(Ostream& os) const
{ {
for (const_iterator iter = this->begin(); iter != this->end(); ++iter)
for
(
typename HashPtrTable<T, Key, Hash>::const_iterator
iter = this->begin();
iter != this->end();
++iter
)
{ {
const T* ptr = *iter; const T* ptr = iter.object();
if (ptr) if (ptr)
{ {
ptr->write(os); ptr->write(os);
@ -215,21 +208,18 @@ template<class T, class Key, class Hash>
Foam::Ostream& Foam::operator<< Foam::Ostream& Foam::operator<<
( (
Ostream& os, Ostream& os,
const HashPtrTable<T, Key, Hash>& L const HashPtrTable<T, Key, Hash>& tbl
) )
{ {
using const_iterator = typename HashPtrTable<T, Key, Hash>::const_iterator;
// Write size and start delimiter // Write size and start delimiter
os << nl << L.size() << nl << token::BEGIN_LIST << nl; os << nl << tbl.size() << nl << token::BEGIN_LIST << nl;
// Write contents // Write contents
for for (const_iterator iter = tbl.cbegin(); iter != tbl.cend(); ++iter)
(
typename HashPtrTable<T, Key, Hash>::const_iterator iter = L.begin();
iter != L.end();
++iter
)
{ {
const T* ptr = *iter; const T* ptr = iter.object();
os << iter.key(); os << iter.key();
if (ptr) if (ptr)

View File

@ -117,20 +117,17 @@ template<class Key, class Hash>
template<class AnyType, class AnyHash> template<class AnyType, class AnyHash>
Foam::HashSet<Key, Hash>::HashSet Foam::HashSet<Key, Hash>::HashSet
( (
const HashTable<AnyType, Key, AnyHash>& h const HashTable<AnyType, Key, AnyHash>& tbl
) )
: :
HashTable<nil, Key, Hash>(h.size()) HashTable<nil, Key, Hash>(tbl.size())
{ {
for using other_iter =
( typename HashTable<AnyType, Key, AnyHash>::const_iterator;
typename HashTable<AnyType, Key, AnyHash>::const_iterator
cit = h.cbegin(); for (other_iter iter = tbl.cbegin(); iter != tbl.cend(); ++iter)
cit != h.cend();
++cit
)
{ {
this->insert(cit.key()); this->insert(iter.key());
} }
} }

View File

@ -132,7 +132,7 @@ public:
//- Construct from the keys of another HashTable, //- Construct from the keys of another HashTable,
// the type of values held is arbitrary. // the type of values held is arbitrary.
template<class AnyType, class AnyHash> template<class AnyType, class AnyHash>
explicit HashSet(const HashTable<AnyType, Key, AnyHash>& h); explicit HashSet(const HashTable<AnyType, Key, AnyHash>& tbl);
// Member Functions // Member Functions

View File

@ -76,7 +76,7 @@ Foam::HashTable<T, Key, Hash>::HashTable(const label size)
for (label hashIdx = 0; hashIdx < tableSize_; hashIdx++) for (label hashIdx = 0; hashIdx < tableSize_; hashIdx++)
{ {
table_[hashIdx] = 0; table_[hashIdx] = nullptr;
} }
} }
} }
@ -89,7 +89,7 @@ Foam::HashTable<T, Key, Hash>::HashTable(const HashTable<T, Key, Hash>& ht)
{ {
for (const_iterator iter = ht.cbegin(); iter != ht.cend(); ++iter) for (const_iterator iter = ht.cbegin(); iter != ht.cend(); ++iter)
{ {
insert(iter.key(), *iter); insert(iter.key(), iter.object());
} }
} }
@ -268,8 +268,8 @@ bool Foam::HashTable<T, Key, Hash>::set
const label hashIdx = hashKeyIndex(key); const label hashIdx = hashKeyIndex(key);
hashedEntry* existing = 0; hashedEntry* existing = nullptr;
hashedEntry* prev = 0; hashedEntry* prev = nullptr;
for (hashedEntry* ep = table_[hashIdx]; ep; ep = ep->next_) for (hashedEntry* ep = table_[hashIdx]; ep; ep = ep->next_)
{ {
@ -281,10 +281,10 @@ bool Foam::HashTable<T, Key, Hash>::set
prev = ep; prev = ep;
} }
// Not found, insert it at the head
if (!existing) if (!existing)
{ {
table_[hashIdx] = new hashedEntry(key, table_[hashIdx], newEntry); // Not found, insert it at the head
table_[hashIdx] = new hashedEntry(key, newEntry, table_[hashIdx]);
nElmts_++; nElmts_++;
if (double(nElmts_)/tableSize_ > 0.8 && tableSize_ < maxTableSize) if (double(nElmts_)/tableSize_ > 0.8 && tableSize_ < maxTableSize)
@ -316,7 +316,7 @@ bool Foam::HashTable<T, Key, Hash>::set
{ {
// Found - overwrite existing entry // Found - overwrite existing entry
// this corresponds to the Perl convention // this corresponds to the Perl convention
hashedEntry* ep = new hashedEntry(key, existing->next_, newEntry); hashedEntry* ep = new hashedEntry(key, newEntry, existing->next_);
// Replace existing element - within list or insert at the head // Replace existing element - within list or insert at the head
if (prev) if (prev)
@ -342,11 +342,11 @@ bool Foam::HashTable<T, Key, Hash>::iteratorBase::erase()
if (entryPtr_) if (entryPtr_)
{ {
// Search element before entryPtr_ // Search element before entryPtr_
hashedEntry* prev = 0; entry_type* prev = nullptr;
for for
( (
hashedEntry* ep = hashTable_->table_[hashIndex_]; entry_type* ep = hashTable_->table_[hashIndex_];
ep; ep;
ep = ep->next_ ep = ep->next_
) )
@ -371,8 +371,7 @@ bool Foam::HashTable<T, Key, Hash>::iteratorBase::erase()
hashTable_->table_[hashIndex_] = entryPtr_->next_; hashTable_->table_[hashIndex_] = entryPtr_->next_;
delete entryPtr_; delete entryPtr_;
// Assign any non-nullptr value so it doesn't look // Assign any non-nullptr value so it doesn't look like end()
// like end()/cend()
entryPtr_ = reinterpret_cast<hashedEntry*>(this); entryPtr_ = reinterpret_cast<hashedEntry*>(this);
// Mark with special hashIndex value to signal it has been rewound. // Mark with special hashIndex value to signal it has been rewound.
@ -547,7 +546,7 @@ void Foam::HashTable<T, Key, Hash>::clear()
ep = next; ep = next;
} }
delete ep; delete ep;
table_[hashIdx] = 0; table_[hashIdx] = nullptr;
} }
} }
nElmts_ = 0; nElmts_ = 0;
@ -625,7 +624,7 @@ void Foam::HashTable<T, Key, Hash>::operator=
for (const_iterator iter = rhs.cbegin(); iter != rhs.cend(); ++iter) for (const_iterator iter = rhs.cbegin(); iter != rhs.cend(); ++iter)
{ {
insert(iter.key(), *iter); insert(iter.key(), iter.object());
} }
} }
@ -667,9 +666,9 @@ bool Foam::HashTable<T, Key, Hash>::operator==
for (const_iterator iter = rhs.cbegin(); iter != rhs.cend(); ++iter) for (const_iterator iter = rhs.cbegin(); iter != rhs.cend(); ++iter)
{ {
const_iterator fnd = find(iter.key()); const_iterator other = find(iter.key());
if (fnd == cend() || fnd() != iter()) if (!other.found() || other.object() != iter.object())
{ {
return false; return false;
} }

View File

@ -37,6 +37,7 @@ Note
SourceFiles SourceFiles
HashTableI.H HashTableI.H
HashTable.C HashTable.C
HashTableCore.C
HashTableIO.C HashTableIO.C
\*---------------------------------------------------------------------------*/ \*---------------------------------------------------------------------------*/
@ -49,6 +50,8 @@ SourceFiles
#include "word.H" #include "word.H"
#include "Xfer.H" #include "Xfer.H"
#include "className.H" #include "className.H"
#include "nullObject.H"
#include <initializer_list> #include <initializer_list>
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@ -71,16 +74,26 @@ template<class T, class Key, class Hash>
Istream& operator>>(Istream& is, HashTable<T, Key, Hash>& L); Istream& operator>>(Istream& is, HashTable<T, Key, Hash>& L);
template<class T, class Key, class Hash> template<class T, class Key, class Hash>
Ostream& operator<<(Ostream& os, const HashTable<T, Key, Hash>& L); Ostream& operator<<(Ostream& os, const HashTable<T, Key, Hash>& tbl);
/*---------------------------------------------------------------------------*\ /*---------------------------------------------------------------------------*\
Class HashTableCore Declaration Class HashTableCore Declaration
\*---------------------------------------------------------------------------*/ \*---------------------------------------------------------------------------*/
//- Template-invariant bits for HashTable //- Template-invariant bits for HashTable.
struct HashTableCore // This also includes a global end-iterator.
//
// The end iterator of all hash-tables has a nullptr to the hash entry.
// Thus avoid separate allocation for each table and use a single one with
// a nullptr.
// The hash-table iterators always have this as its first member data,
// so we can reinterpret_cast from anything else that has a nullptr for its
// first data member. This is now also the case for the NullObject.
class HashTableCore
{ {
public:
//- Return a canonical (power-of-two) size //- Return a canonical (power-of-two) size
static label canonicalSize(const label size); static label canonicalSize(const label size);
@ -94,24 +107,20 @@ struct HashTableCore
//- Define template name and debug //- Define template name and debug
ClassName("HashTable"); ClassName("HashTable");
//- A zero-sized end iterator
struct iteratorEnd
{
//- Construct null
iteratorEnd()
{}
};
//- iteratorEnd set to beyond the end of any HashTable protected:
inline static iteratorEnd cend()
{
return iteratorEnd();
}
//- iteratorEnd set to beyond the end of any HashTable static_assert
inline static iteratorEnd end() (
sizeof(NullObject) >= sizeof(void*),
"NullObject is too small to reinterpret_cast as HashTable::iterator"
);
//- Reinterpret a NullObject as a hash-table iterator.
template<class Iterator>
inline static const Iterator& endIteratorRef()
{ {
return iteratorEnd(); return *reinterpret_cast<const Iterator*>(nullObjectPtr);
} }
}; };
@ -133,14 +142,14 @@ class HashTable
//- The lookup key //- The lookup key
Key key_; Key key_;
//- Pointer to next hashedEntry in sub-list
hashedEntry* next_;
//- The data object //- The data object
T obj_; T obj_;
//- Pointer to next hashedEntry in sub-list
hashedEntry* next_;
//- Construct from key, next pointer and object //- Construct from key, next pointer and object
inline hashedEntry(const Key& key, hashedEntry* next, const T& obj); inline hashedEntry(const Key& key, const T& obj, hashedEntry* next);
private: private:
@ -170,7 +179,7 @@ class HashTable
// No checks for zero-sized tables. // No checks for zero-sized tables.
inline label hashKeyIndex(const Key& key) const; inline label hashKeyIndex(const Key& key) const;
//- Assign a new hashedEntry to a possibly already existing key. //- Assign a new hash-entry to a possibly already existing key.
// Return true if the new entry was set. // Return true if the new entry was set.
bool set(const Key& key, const T& newEntry, const bool protect); bool set(const Key& key, const T& newEntry, const bool protect);
@ -187,6 +196,7 @@ protected:
const InputIter endIter const InputIter endIter
); );
public: public:
// Forward declaration of iterators // Forward declaration of iterators
@ -195,19 +205,9 @@ public:
class iterator; class iterator;
class const_iterator; class const_iterator;
//- Declare friendship with the HashPtrTable class
template<class T2, class Key2, class Hash2>
friend class HashPtrTable;
//- Declare friendship with the iteratorBase //- Declare friendship with the iteratorBase
friend class iteratorBase; friend class iteratorBase;
//- Declare friendship with the iterator
friend class iterator;
//- Declare friendship with the const_iterator
friend class const_iterator;
// Constructors // Constructors
@ -351,10 +351,12 @@ public:
bool operator!=(const HashTable<T, Key, Hash>& rhs) const; bool operator!=(const HashTable<T, Key, Hash>& rhs) const;
// STL type definitions // STL type definitions
//- Type of values the HashTable contains. //- Type of keys that the HashTable uses.
typedef Key key_type;
//- Type of values that the HashTable contains.
typedef T value_type; typedef T value_type;
//- Type that can be used for storing into HashTable::value_type //- Type that can be used for storing into HashTable::value_type
@ -370,6 +372,27 @@ public:
typedef label size_type; typedef label size_type;
// Iterator access
//- Iterator set to the beginning of the HashTable
inline iterator begin();
//- const_iterator set to the beginning of the HashTable
inline const_iterator begin() const;
//- const_iterator set to the beginning of the HashTable
inline const_iterator cbegin() const;
//- iterator to signal the end for any HashTable
inline const iterator& end();
//- const_iterator to signal the end for any HashTable
inline const const_iterator& end() const;
//- const_iterator to signal the end for any HashTable
inline const const_iterator& cend() const;
// Iterators and helpers // Iterators and helpers
//- The iterator base for HashTable //- The iterator base for HashTable
@ -379,133 +402,125 @@ public:
// us to reinterpret_cast between them (if desired) // us to reinterpret_cast between them (if desired)
class iteratorBase class iteratorBase
{ {
using entry_type = hashedEntry;
public:
// Public typedefs
using table_type = HashTable<T, Key, Hash>;
using key_type = HashTable<T, Key, Hash>::key_type;
private:
// Private Data // Private Data
//- Pointer to the HashTable for which this is an iterator //- Currently selected entry.
// MUST be the first member for easy comparison between iterators
// and for reinterpret_cast from nullObject
entry_type* entryPtr_;
//- Pointer to the hash-table for which this is an iterator
// This allows use of the default bitwise copy/assignment // This allows use of the default bitwise copy/assignment
HashTable<T, Key, Hash>* hashTable_; table_type* hashTable_;
//- Current element //- Current hash index within the hash-table data.
hashedEntry* entryPtr_; // A signed value, since erase() uses a negative value to signal
// the erasure state.
//- Current hash index
label hashIndex_; label hashIndex_;
protected: protected:
// Constructors
//- Construct null - equivalent to an 'end' position
inline iteratorBase();
//- Construct from hash table, moving to its 'begin' position
inline explicit iteratorBase
(
const HashTable<T, Key, Hash>* hashTbl
);
//- Construct from hash table, element and hash index
inline iteratorBase
(
const HashTable<T, Key, Hash>* hashTbl,
const hashedEntry* elmt,
const label hashIndex
);
// Protected Member Functions // Protected Member Functions
//- Increment to the next position //- Increment to the next position
inline void increment(); inline void increment();
//- Erase the HashTable element at the current position //- Erase the entry at the current position
bool erase(); bool erase();
//- Return non-const access to referenced object //- The referenced object/value element
inline T& object(); inline T& element() const;
public:
// Member operators
// Access
//- True if iterator points to a hashedEntry.
// This can be used instead of a comparison to end()
inline bool found() const;
//- Return the Key corresponding to the iterator
inline const Key& key() const;
//- Return const access to referenced object
inline const T& cobject() const;
//- Compare hashedEntry element pointers
inline bool operator==(const iteratorBase& iter) const;
inline bool operator!=(const iteratorBase& iter) const;
//- Compare hashedEntry to iteratorEnd pointers
inline bool operator==(const iteratorEnd& unused) const;
inline bool operator!=(const iteratorEnd& unused) const;
};
//- An STL-conforming iterator
class iterator
:
public iteratorBase
{
friend class HashTable;
// Private Member Functions
//- Construct from hash table, moving to its 'begin' position
inline explicit iterator
(
HashTable<T, Key, Hash>* hashTbl
);
//- Construct from hash table, element and hash index
inline iterator
(
HashTable<T, Key, Hash>* hashTbl,
hashedEntry* elmt,
const label hashIndex
);
public: public:
// Constructors
//- Construct null (end iterator)
inline iteratorBase();
//- Construct from begin of hash-table
inline explicit iteratorBase(const table_type* hashTbl);
//- Construct from hash table, element and hash index
inline iteratorBase
(
const table_type* hashTbl,
const entry_type* elmt,
const label hashIndex
);
// Member functions/operators
//- True if iterator points to an entry
// This can be used directly instead of comparing to end()
inline bool found() const;
//- Return the Key corresponding to the iterator
inline const Key& key() const;
//- Compare hash-entry element pointers
inline bool operator==(const iteratorBase& iter) const;
inline bool operator!=(const iteratorBase& iter) const;
};
// STL iterator
//- An STL-conforming iterator
class iterator
:
public iteratorBase
{
friend class HashTable; // uses iterator::erase() method
using entry_type = hashedEntry;
public:
// Public typedefs
using table_type = HashTable<T, Key, Hash>;
using key_type = HashTable<T, Key, Hash>::key_type;
using reference = HashTable<T, Key, Hash>::reference;
// Constructors // Constructors
//- Construct null (end iterator) //- Construct null (end iterator)
inline iterator(); inline iterator();
//- Construct end iterator //- Construct from begin of hash-table
inline iterator(const iteratorEnd& unused); inline explicit iterator(table_type* hashTbl);
//- Construct from hash table, element and hash index
// Used by the hash-table find() method.
inline iterator
(
table_type* hashTbl,
entry_type* elmt,
const label hashIndex
);
// Member operators // Member functions/operators
//- Return non-const access to referenced object //- Return non-const access to referenced object
using iteratorBase::object; inline reference object() const;
//- Return non-const access to referenced object //- Return non-const access to referenced object
inline T& operator*(); inline reference operator*() const;
inline T& operator()(); inline reference operator()() const;
//- Return const access to referenced object
inline const T& operator*() const;
inline const T& operator()() const;
inline iterator& operator++(); inline iterator& operator++();
inline iterator operator++(int); inline iterator operator++(int);
}; };
//- Iterator set to the beginning of the HashTable
inline iterator begin();
// STL const_iterator // STL const_iterator
@ -514,56 +529,49 @@ public:
: :
public iteratorBase public iteratorBase
{ {
friend class HashTable; using entry_type = const hashedEntry;
// Private Member Functions
//- Construct from hash table, moving to its 'begin' position
inline explicit const_iterator
(
const HashTable<T, Key, Hash>* hashTbl
);
//- Construct from hash table, element and hash index
inline const_iterator
(
const HashTable<T, Key, Hash>* hashTbl,
const hashedEntry* elmt,
const label hashIndex
);
public: public:
// Public typedefs
using table_type = const HashTable<T, Key, Hash>;
using key_type = HashTable<T, Key, Hash>::key_type;
using reference = HashTable<T, Key, Hash>::const_reference;
// Constructors // Constructors
//- Construct null (end iterator) //- Construct null (end iterator)
inline const_iterator(); inline const_iterator();
//- Construct from iterator //- Construct from begin of hash-table
inline explicit const_iterator(table_type* hashTbl);
//- Construct from hash table, element and hash index.
// Used by the hash-table find() method.
inline const_iterator
(
table_type* hashTbl,
entry_type* elmt,
const label hashIndex
);
//- Copy construct from iterator
inline const_iterator(const iterator& iter); inline const_iterator(const iterator& iter);
//- Construct end iterator // Member functions/operators
inline const_iterator(const iteratorEnd& unused);
// Member operators
//- Return const access to referenced object //- Return const access to referenced object
inline const T& operator*() const; inline reference object() const;
inline const T& operator()() const;
//- Return const access to referenced object
inline reference operator*() const;
inline reference operator()() const;
inline const_iterator& operator++(); inline const_iterator& operator++();
inline const_iterator operator++(int); inline const_iterator operator++(int);
}; };
//- const_iterator set to the beginning of the HashTable
inline const_iterator cbegin() const;
//- const_iterator set to the beginning of the HashTable
inline const_iterator begin() const;
// IOstream Operator // IOstream Operator
@ -576,7 +584,7 @@ public:
friend Ostream& operator<< <T, Key, Hash> friend Ostream& operator<< <T, Key, Hash>
( (
Ostream& os, Ostream& os,
const HashTable<T, Key, Hash>& L const HashTable<T, Key, Hash>& tbl
); );
}; };
@ -587,7 +595,7 @@ public:
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#include "HashTableI.H" #include "HashTableI.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

View File

@ -31,13 +31,13 @@ template<class T, class Key, class Hash>
inline Foam::HashTable<T, Key, Hash>::hashedEntry::hashedEntry inline Foam::HashTable<T, Key, Hash>::hashedEntry::hashedEntry
( (
const Key& key, const Key& key,
hashedEntry* next, const T& obj,
const T& obj hashedEntry* next
) )
: :
key_(key), key_(key),
next_(next), obj_(obj),
obj_(obj) next_(next)
{} {}
@ -112,7 +112,7 @@ inline T& Foam::HashTable<T, Key, Hash>::operator[](const Key& key)
{ {
iterator iter = this->find(key); iterator iter = this->find(key);
if (iter == this->end()) if (!iter.found())
{ {
FatalErrorInFunction FatalErrorInFunction
<< key << " not found in table. Valid entries: " << key << " not found in table. Valid entries: "
@ -120,7 +120,7 @@ inline T& Foam::HashTable<T, Key, Hash>::operator[](const Key& key)
<< exit(FatalError); << exit(FatalError);
} }
return *iter; return iter.object();
} }
@ -129,7 +129,7 @@ inline const T& Foam::HashTable<T, Key, Hash>::operator[](const Key& key) const
{ {
const_iterator iter = this->find(key); const_iterator iter = this->find(key);
if (iter == this->cend()) if (!iter.found())
{ {
FatalErrorInFunction FatalErrorInFunction
<< key << " not found in table. Valid entries: " << key << " not found in table. Valid entries: "
@ -137,7 +137,7 @@ inline const T& Foam::HashTable<T, Key, Hash>::operator[](const Key& key) const
<< exit(FatalError); << exit(FatalError);
} }
return *iter; return iter.object();
} }
@ -146,15 +146,13 @@ inline T& Foam::HashTable<T, Key, Hash>::operator()(const Key& key)
{ {
iterator iter = this->find(key); iterator iter = this->find(key);
if (iter == this->end()) if (iter.found())
{ {
return iter.object();
}
this->insert(key, T()); this->insert(key, T());
return *find(key); return find(key).object();
}
else
{
return *iter;
}
} }
@ -163,8 +161,8 @@ inline T& Foam::HashTable<T, Key, Hash>::operator()(const Key& key)
template<class T, class Key, class Hash> template<class T, class Key, class Hash>
inline Foam::HashTable<T, Key, Hash>::iteratorBase::iteratorBase() inline Foam::HashTable<T, Key, Hash>::iteratorBase::iteratorBase()
: :
hashTable_(0), entryPtr_(nullptr),
entryPtr_(0), hashTable_(nullptr),
hashIndex_(0) hashIndex_(0)
{} {}
@ -172,14 +170,28 @@ inline Foam::HashTable<T, Key, Hash>::iteratorBase::iteratorBase()
template<class T, class Key, class Hash> template<class T, class Key, class Hash>
inline Foam::HashTable<T, Key, Hash>::iteratorBase::iteratorBase inline Foam::HashTable<T, Key, Hash>::iteratorBase::iteratorBase
( (
const HashTable<T, Key, Hash>* hashTbl const table_type* hashTbl,
const entry_type* elmt,
const label hashIndex
) )
: :
hashTable_(const_cast<HashTable<T, Key, Hash>*>(hashTbl)), entryPtr_(const_cast<entry_type*>(elmt)),
entryPtr_(0), hashTable_(const_cast<table_type*>(hashTbl)),
hashIndex_(hashIndex)
{}
template<class T, class Key, class Hash>
inline Foam::HashTable<T, Key, Hash>::iteratorBase::iteratorBase
(
const table_type* hashTbl
)
:
entryPtr_(nullptr),
hashTable_(const_cast<table_type*>(hashTbl)),
hashIndex_(0) hashIndex_(0)
{ {
if (hashTable_->nElmts_) if (hashTable_ && hashTable_->nElmts_)
{ {
// find first non-nullptr table entry // find first non-nullptr table entry
while while
@ -192,27 +204,13 @@ inline Foam::HashTable<T, Key, Hash>::iteratorBase::iteratorBase
if (hashIndex_ >= hashTable_->tableSize_) if (hashIndex_ >= hashTable_->tableSize_)
{ {
// make into an end iterator // make into an end iterator
entryPtr_ = 0; entryPtr_ = nullptr;
hashIndex_ = 0; hashIndex_ = 0;
} }
} }
} }
template<class T, class Key, class Hash>
inline Foam::HashTable<T, Key, Hash>::iteratorBase::iteratorBase
(
const HashTable<T, Key, Hash>* hashTbl,
const hashedEntry* elmt,
const label hashIndex
)
:
hashTable_(const_cast<HashTable<T, Key, Hash>*>(hashTbl)),
entryPtr_(const_cast<hashedEntry*>(elmt)),
hashIndex_(hashIndex)
{}
template<class T, class Key, class Hash> template<class T, class Key, class Hash>
inline void inline void
Foam::HashTable<T, Key, Hash>::iteratorBase::increment() Foam::HashTable<T, Key, Hash>::iteratorBase::increment()
@ -251,7 +249,7 @@ Foam::HashTable<T, Key, Hash>::iteratorBase::increment()
if (hashIndex_ >= hashTable_->tableSize_) if (hashIndex_ >= hashTable_->tableSize_)
{ {
// make into an end iterator // make into an end iterator
entryPtr_ = 0; entryPtr_ = nullptr;
hashIndex_ = 0; hashIndex_ = 0;
} }
} }
@ -266,24 +264,14 @@ Foam::HashTable<T, Key, Hash>::iteratorBase::found() const
template<class T, class Key, class Hash> template<class T, class Key, class Hash>
inline inline const Key& Foam::HashTable<T, Key, Hash>::iteratorBase::key() const
const Key& Foam::HashTable<T, Key, Hash>::iteratorBase::key() const
{ {
return entryPtr_->key_; return entryPtr_->key_;
} }
template<class T, class Key, class Hash> template<class T, class Key, class Hash>
inline T& inline T& Foam::HashTable<T, Key, Hash>::iteratorBase::element() const
Foam::HashTable<T, Key, Hash>::iteratorBase::object()
{
return entryPtr_->obj_;
}
template<class T, class Key, class Hash>
inline const T&
Foam::HashTable<T, Key, Hash>::iteratorBase::cobject() const
{ {
return entryPtr_->obj_; return entryPtr_->obj_;
} }
@ -309,26 +297,6 @@ inline bool Foam::HashTable<T, Key, Hash>::iteratorBase::operator!=
} }
template<class T, class Key, class Hash>
inline bool Foam::HashTable<T, Key, Hash>::iteratorBase::operator==
(
const iteratorEnd&
) const
{
return !entryPtr_;
}
template<class T, class Key, class Hash>
inline bool Foam::HashTable<T, Key, Hash>::iteratorBase::operator!=
(
const iteratorEnd&
) const
{
return entryPtr_;
}
// * * * * * * * * * * * * * * * * STL iterator * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * STL iterator * * * * * * * * * * * * * * //
template<class T, class Key, class Hash> template<class T, class Key, class Hash>
@ -341,17 +309,7 @@ inline Foam::HashTable<T, Key, Hash>::iterator::iterator()
template<class T, class Key, class Hash> template<class T, class Key, class Hash>
inline Foam::HashTable<T, Key, Hash>::iterator::iterator inline Foam::HashTable<T, Key, Hash>::iterator::iterator
( (
const iteratorEnd& table_type* hashTbl
)
:
iteratorBase()
{}
template<class T, class Key, class Hash>
inline Foam::HashTable<T, Key, Hash>::iterator::iterator
(
HashTable<T, Key, Hash>* hashTbl
) )
: :
iteratorBase(hashTbl) iteratorBase(hashTbl)
@ -361,8 +319,8 @@ inline Foam::HashTable<T, Key, Hash>::iterator::iterator
template<class T, class Key, class Hash> template<class T, class Key, class Hash>
inline Foam::HashTable<T, Key, Hash>::iterator::iterator inline Foam::HashTable<T, Key, Hash>::iterator::iterator
( (
HashTable<T, Key, Hash>* hashTbl, table_type* hashTbl,
hashedEntry* elmt, entry_type* elmt,
const label hashIndex const label hashIndex
) )
: :
@ -372,7 +330,15 @@ inline Foam::HashTable<T, Key, Hash>::iterator::iterator
template<class T, class Key, class Hash> template<class T, class Key, class Hash>
inline T& inline T&
Foam::HashTable<T, Key, Hash>::iterator::operator*() Foam::HashTable<T, Key, Hash>::iterator::object() const
{
return this->element();
}
template<class T, class Key, class Hash>
inline T&
Foam::HashTable<T, Key, Hash>::iterator::operator*() const
{ {
return this->object(); return this->object();
} }
@ -380,31 +346,14 @@ Foam::HashTable<T, Key, Hash>::iterator::operator*()
template<class T, class Key, class Hash> template<class T, class Key, class Hash>
inline T& inline T&
Foam::HashTable<T, Key, Hash>::iterator::operator()() Foam::HashTable<T, Key, Hash>::iterator::operator()() const
{ {
return this->object(); return this->object();
} }
template<class T, class Key, class Hash> template<class T, class Key, class Hash>
inline const T& inline typename Foam::HashTable<T, Key, Hash>::iterator&
Foam::HashTable<T, Key, Hash>::iterator::operator*() const
{
return this->cobject();
}
template<class T, class Key, class Hash>
inline const T&
Foam::HashTable<T, Key, Hash>::iterator::operator()() const
{
return this->cobject();
}
template<class T, class Key, class Hash>
inline
typename Foam::HashTable<T, Key, Hash>::iterator&
Foam::HashTable<T, Key, Hash>::iterator::operator++() Foam::HashTable<T, Key, Hash>::iterator::operator++()
{ {
this->increment(); this->increment();
@ -422,14 +371,6 @@ Foam::HashTable<T, Key, Hash>::iterator::operator++(int)
} }
template<class T, class Key, class Hash>
inline typename Foam::HashTable<T, Key, Hash>::iterator
Foam::HashTable<T, Key, Hash>::begin()
{
return iterator(this);
}
// * * * * * * * * * * * * * * * STL const_iterator * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * STL const_iterator * * * * * * * * * * * * * //
template<class T, class Key, class Hash> template<class T, class Key, class Hash>
@ -452,17 +393,7 @@ inline Foam::HashTable<T, Key, Hash>::const_iterator::const_iterator
template<class T, class Key, class Hash> template<class T, class Key, class Hash>
inline Foam::HashTable<T, Key, Hash>::const_iterator::const_iterator inline Foam::HashTable<T, Key, Hash>::const_iterator::const_iterator
( (
const iteratorEnd& table_type* hashTbl
)
:
iteratorBase()
{}
template<class T, class Key, class Hash>
inline Foam::HashTable<T, Key, Hash>::const_iterator::const_iterator
(
const HashTable<T, Key, Hash>* hashTbl
) )
: :
iteratorBase(hashTbl) iteratorBase(hashTbl)
@ -472,8 +403,8 @@ inline Foam::HashTable<T, Key, Hash>::const_iterator::const_iterator
template<class T, class Key, class Hash> template<class T, class Key, class Hash>
inline Foam::HashTable<T, Key, Hash>::const_iterator::const_iterator inline Foam::HashTable<T, Key, Hash>::const_iterator::const_iterator
( (
const HashTable<T, Key, Hash>* hashTbl, table_type* hashTbl,
const hashedEntry* elmt, entry_type* elmt,
const label hashIndex const label hashIndex
) )
: :
@ -481,11 +412,19 @@ inline Foam::HashTable<T, Key, Hash>::const_iterator::const_iterator
{} {}
template<class T, class Key, class Hash>
inline const T&
Foam::HashTable<T, Key, Hash>::const_iterator::object() const
{
return this->element();
}
template<class T, class Key, class Hash> template<class T, class Key, class Hash>
inline const T& inline const T&
Foam::HashTable<T, Key, Hash>::const_iterator::operator*() const Foam::HashTable<T, Key, Hash>::const_iterator::operator*() const
{ {
return this->cobject(); return this->object();
} }
@ -493,13 +432,12 @@ template<class T, class Key, class Hash>
inline const T& inline const T&
Foam::HashTable<T, Key, Hash>::const_iterator::operator()() const Foam::HashTable<T, Key, Hash>::const_iterator::operator()() const
{ {
return this->cobject(); return this->object();
} }
template<class T, class Key, class Hash> template<class T, class Key, class Hash>
inline inline typename Foam::HashTable<T, Key, Hash>::const_iterator&
typename Foam::HashTable<T, Key, Hash>::const_iterator&
Foam::HashTable<T, Key, Hash>::const_iterator::operator++() Foam::HashTable<T, Key, Hash>::const_iterator::operator++()
{ {
this->increment(); this->increment();
@ -517,6 +455,16 @@ Foam::HashTable<T, Key, Hash>::const_iterator::operator++(int)
} }
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
template<class T, class Key, class Hash>
inline typename Foam::HashTable<T, Key, Hash>::iterator
Foam::HashTable<T, Key, Hash>::begin()
{
return iterator(this);
}
template<class T, class Key, class Hash> template<class T, class Key, class Hash>
inline typename Foam::HashTable<T, Key, Hash>::const_iterator inline typename Foam::HashTable<T, Key, Hash>::const_iterator
Foam::HashTable<T, Key, Hash>::cbegin() const Foam::HashTable<T, Key, Hash>::cbegin() const
@ -529,7 +477,37 @@ template<class T, class Key, class Hash>
inline typename Foam::HashTable<T, Key, Hash>::const_iterator inline typename Foam::HashTable<T, Key, Hash>::const_iterator
Foam::HashTable<T, Key, Hash>::begin() const Foam::HashTable<T, Key, Hash>::begin() const
{ {
return this->cbegin(); return const_iterator(this);
}
template<class T, class Key, class Hash>
inline const typename Foam::HashTable<T, Key, Hash>::iterator&
Foam::HashTable<T, Key, Hash>::end()
{
using iter_type = typename HashTable<T, Key, Hash>::iterator;
return endIteratorRef<iter_type>();
}
template<class T, class Key, class Hash>
inline const typename Foam::HashTable<T, Key, Hash>::const_iterator&
Foam::HashTable<T, Key, Hash>::cend() const
{
using iter_type = typename HashTable<T, Key, Hash>::const_iterator;
return endIteratorRef<iter_type>();
}
template<class T, class Key, class Hash>
inline const typename Foam::HashTable<T, Key, Hash>::const_iterator&
Foam::HashTable<T, Key, Hash>::end() const
{
using iter_type = typename HashTable<T, Key, Hash>::const_iterator;
return endIteratorRef<iter_type>();
} }

View File

@ -3,7 +3,7 @@
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration | \\ / O peration |
\\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation \\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
\\/ M anipulation | \\/ M anipulation | Copyright (C) 2017 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -43,7 +43,7 @@ Foam::HashTable<T, Key, Hash>::HashTable(Istream& is, const label size)
for (label hashIdx = 0; hashIdx < tableSize_; ++hashIdx) for (label hashIdx = 0; hashIdx < tableSize_; ++hashIdx)
{ {
table_[hashIdx] = 0; table_[hashIdx] = nullptr;
} }
} }
@ -215,21 +215,18 @@ template<class T, class Key, class Hash>
Foam::Ostream& Foam::operator<< Foam::Ostream& Foam::operator<<
( (
Ostream& os, Ostream& os,
const HashTable<T, Key, Hash>& L const HashTable<T, Key, Hash>& tbl
) )
{ {
using const_iterator = typename HashTable<T, Key, Hash>::const_iterator;
// Write size and start delimiter // Write size and start delimiter
os << nl << L.size() << nl << token::BEGIN_LIST << nl; os << nl << tbl.size() << nl << token::BEGIN_LIST << nl;
// Write contents // Write contents
for for (const_iterator iter = tbl.cbegin(); iter != tbl.cend(); ++iter)
(
typename HashTable<T, Key, Hash>::const_iterator iter = L.cbegin();
iter != L.cend();
++iter
)
{ {
os << iter.key() << token::SPACE << iter() << nl; os << iter.key() << token::SPACE << iter.object() << nl;
} }
// Write end delimiter // Write end delimiter

View File

@ -119,9 +119,6 @@ class StaticHashTable
//- The current number of elements in table //- The current number of elements in table
label nElmts_; label nElmts_;
//- Return a canonical (power-of-two) size
static label canonicalSize(const label);
//- Return the hash index of the Key within the current table size. //- Return the hash index of the Key within the current table size.
// No checks for zero-sized tables. // No checks for zero-sized tables.
inline label hashKeyIndex(const Key&) const; inline label hashKeyIndex(const Key&) const;
@ -397,7 +394,7 @@ private:
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#include "StaticHashTableI.H" #include "StaticHashTableI.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //