ENH: adjust HashTable iterator access

- previously allowed mapped value modification with a const iterator.
  However, this can lead to incorrect access patterns.

  Now tie the constness of the mapped value to that of the iterator.

- Remove deprecated iterator object() method.
  Was only used internally and was superseded by the val() method
  in an earlier version.

ENH: change isPointer to isPointerLike

- can distinguish between real pointers and wrapped pointers
This commit is contained in:
Mark Olesen
2019-09-25 12:21:54 +02:00
committed by Andrew Heather
parent b931e267fe
commit bc9295ee04
2 changed files with 57 additions and 42 deletions

View File

@ -170,11 +170,11 @@ public:
//- The third template parameter, the hash index method.
typedef Hash hasher;
//- The type used for storing into value_type objects.
//- Reference to the stored value_type.
// This type is usually 'value_type&'.
typedef T& reference;
//- The type used for reading from constant value_type objects.
//- Const reference to the stored value_type.
typedef const T& const_reference;
//- The type to represent the difference between two iterators
@ -647,19 +647,6 @@ protected:
//- Increment to the next position
inline void increment();
//- The value associated with the iterator
inline mapped_type& val() const
{
return entry_->mapped();
}
//- The object (value) associated with the iterator
// \deprecated(2019-01) use val() method
inline mapped_type& object() const
{
return entry_->mapped();
}
//- Permit an explicit cast to the other (const/non-const) searcher
inline explicit operator const Iterator<!Const>&() const
{
@ -689,6 +676,8 @@ public:
using mapped_type = this_type::mapped_type;
using value_type = this_type::value_type;
using reference = this_type::reference;
using const_reference = this_type::const_reference;
// Constructors
@ -704,15 +693,25 @@ public:
// Member Functions/Operators
//- Const access to referenced object (value)
inline const_reference val() const
{
return Iterator<false>::entry_->cval();
}
//- Non-const access to referenced object (value)
using Iterator<false>::val;
inline reference val()
{
return Iterator<false>::entry_->val();
}
//- Non-const access to referenced object
using Iterator<false>::object;
//- Const access to referenced object (value)
inline const_reference operator*() const { return this->val(); }
inline const_reference operator()() const { return this->val(); }
//- Non-const access to referenced object
inline reference operator*() const { return this->val(); }
inline reference operator()() const { return this->val(); }
//- Non-const access to referenced object (value)
inline reference operator*() { return this->val(); }
inline reference operator()() { return this->val(); }
inline iterator& operator++();
inline iterator operator++(int);
@ -736,6 +735,7 @@ public:
using value_type = const this_type::value_type;
using reference = this_type::const_reference;
// Constructors
//- Construct null (end iterator)
@ -765,13 +765,13 @@ public:
// Member Functions/Operators
//- Const access to referenced value
using Iterator<true>::val;
//- Const access to referenced object (value)
inline const reference val() const
{
return Iterator<true>::entry_->cval();
}
//- Const access to referenced object (value)
using Iterator<true>::object;
//- Const access to referenced value
inline reference operator*() const { return this->val(); }
inline reference operator()() const { return this->val(); }

View File

@ -53,17 +53,17 @@ namespace Detail
{
/*---------------------------------------------------------------------------*\
Class isPointer Declaration
Class isPointerLike Declaration
\*---------------------------------------------------------------------------*/
//- Pointer-like behaviour
template<class T> struct isPointer : std::is_pointer<T> {};
template<class T> struct isPointerLike : std::false_type {};
//- Pointer-like behaviour for autoPtr
template<class T> struct isPointer<autoPtr<T>> : std::true_type {};
template<class T> struct isPointerLike<autoPtr<T>> : std::true_type {};
//- Pointer-like behaviour for std::unique_ptr
template<class T> struct isPointer<std::unique_ptr<T>> : std::true_type {};
template<class T> struct isPointerLike<std::unique_ptr<T>> : std::true_type {};
/*---------------------------------------------------------------------------*\
@ -86,7 +86,7 @@ struct HashTablePair
typedef V mapped_type;
//- This struct stores a value
static constexpr bool stores_value()
static constexpr bool stores_value() noexcept
{
return true;
}
@ -134,21 +134,28 @@ struct HashTablePair
return key_;
}
//- The mapped value
const mapped_type& mapped() const
//- Const access to the mapped value
const mapped_type& cval() const
{
return val_;
}
//- The mapped value
mapped_type& mapped()
//- Non-const access to the mapped value
mapped_type& val()
{
return val_;
}
//- Write (key, val) pair - for pointer types
template<class TypeT = V>
typename std::enable_if<Detail::isPointer<TypeT>::value, void>::type
typename std::enable_if
<
(
std::is_pointer<TypeT>::value
|| Detail::isPointerLike<TypeT>::value
),
void
>::type
print(Ostream& os) const
{
os << key_;
@ -161,7 +168,14 @@ struct HashTablePair
//- Write (key, val) pair - for non-pointer types
template<class TypeT = V>
typename std::enable_if<!Detail::isPointer<TypeT>::value, void>::type
typename std::enable_if
<
(
!std::is_pointer<TypeT>::value
&& !Detail::isPointerLike<TypeT>::value
),
void
>::type
print(Ostream& os) const
{
os << key_ << ' ' << val_;
@ -190,11 +204,12 @@ struct HashTableSingle
typedef key_type value_type;
//- This struct does not store a value
static constexpr bool stores_value()
static constexpr bool stores_value() noexcept
{
return false;
}
// Member Data
//- The lookup key == content
@ -233,14 +248,14 @@ struct HashTableSingle
return key_;
}
//- The mapped value (dummy)
const mapped_type& mapped() const
//- Const access to the (dummy) mapped value
const mapped_type& cval() const
{
return Foam::zero::null::dummy;
}
//- The mapped value (dummy)
mapped_type& mapped()
//- Non-const access to the (dummy) mapped value
mapped_type& val()
{
return Foam::zero::null::dummy;
}