// hash_set standard header -*-c++-*-
// Copyright 2003-2020 IAR Systems AB. 
#ifndef _DLIB5_HASH_SET_
#define _DLIB5_HASH_SET_

#ifndef _SYSTEM_BUILD
#pragma system_include
#endif

#include <dlib5/xhash>
_DLIB5_BEGIN

#pragma language = save
#pragma language = extended
// TEMPLATE CLASS _Hset_traits
template<class _Kty,    // key type (same as value type)
         class _Tr,      // comparator predicate type
         class _Alloc,   // actual allocator type (should be value allocator)
         bool _Mfl>      // true if multiple equivalent keys are permitted
class __memory_of(_Kty) _Hset_traits
{       // traits required to make _Hash behave like a set
public:
  typedef _Kty key_type;
  typedef _Kty value_type;
  typedef _Tr key_compare;
  typedef typename _Alloc::template rebind<value_type>::other
    allocator_type;
  enum
  {       // make multi parameter visible as an enum constant
    _Multi = _Mfl
  };
  typedef typename _TypeUtil::_ParameterType<value_type>::_Type _ValParamTy;

  _Hset_traits()
    : _Kcmp()
  {}      // construct with default comparator

  _Hset_traits(const _Tr& _Traits)
    : _Kcmp(_Traits)
  {}      // construct with specified comparator

  typedef key_compare value_compare;

  static _ValParamTy _Kfn(_ValParamTy _Val)
  {       // return entire value as key
      return (_Val); 
  }

  _ClassUtil::_MemHolder<value_type, _Tr>
                              _Kcmp;       // the comparator predicate for keys

  key_compare   comp() const { return _Kcmp; }
  key_compare & comp()       { return _Kcmp; }
};

// TEMPLATE CLASS hash_set
template<class _Kty,
         class _Tr = hash_compare<_Kty, less<_Kty> >,
         class _Alloc = allocator<_Kty> >
class hash_set
: public _Hash<_Hset_traits<_Kty, _Tr, _Alloc, false> >
{       // hash table of key values, unique keys
public:
  typedef _Hash<_Hset_traits<_Kty, _Tr, _Alloc, false> > _Mybase;
  typedef _Kty key_type;
  typedef _Tr key_compare;
  typedef typename _Mybase::value_compare value_compare;
  typedef typename _Mybase::allocator_type allocator_type;
  typedef typename _Mybase::size_type size_type;
  typedef typename _Mybase::difference_type difference_type;
  typedef typename _Mybase::pointer pointer;
  typedef typename _Mybase::const_pointer const_pointer;
  typedef typename _Mybase::reference reference;
  typedef typename _Mybase::const_reference const_reference;
  typedef typename _Mybase::iterator iterator;
  typedef typename _Mybase::const_iterator const_iterator;
  typedef typename _Mybase::reverse_iterator reverse_iterator;
  typedef typename _Mybase::const_reverse_iterator
  const_reverse_iterator;
  typedef typename _Mybase::value_type value_type;

  hash_set()
  : _Mybase(key_compare(), allocator_type())
  {}      // construct empty set from defaults

  explicit hash_set(const key_compare& _Traits)
  : _Mybase(_Traits, allocator_type())
  {}      // construct empty set from comparator

  hash_set(const key_compare& _Traits, const allocator_type& _Al)
  : _Mybase(_Traits, _Al)
  {}      // construct empty set from comparator and allocator

  template<class _Iter>
  hash_set(_Iter _First, _Iter _Last)
  : _Mybase(key_compare(), allocator_type())
  {       // construct set from sequence, defaults
    for (; _First != _Last; ++_First)
    this->insert(*_First); 
  }

  template<class _Iter>
  hash_set(_Iter _First, _Iter _Last, const key_compare& _Traits)
  : _Mybase(_Traits, allocator_type())
  {       // construct set from sequence, comparator
    for (; _First != _Last; ++_First)
    this->insert(*_First); 
  }

  template<class _Iter>
  hash_set(_Iter _First, _Iter _Last, const key_compare& _Traits,
           const allocator_type& _Al)
  : _Mybase(_Traits, _Al)
  {       // construct set from sequence, comparator, and allocator
    for (; _First != _Last; ++_First)
    this->insert(*_First); 
  }
};

// TEMPLATE CLASS hash_multiset
template<class _Kty,
         class _Tr = hash_compare<_Kty, less<_Kty> >,
         class _Alloc = allocator<_Kty> >
class hash_multiset
: public _Hash<_Hset_traits<_Kty, _Tr, _Alloc, true> >
{       // hash table of key values, non-unique keys
public:
  typedef _Hash<_Hset_traits<_Kty, _Tr, _Alloc, true> > _Mybase;
  typedef _Kty key_type;
  typedef _Tr key_compare;
  typedef typename _Mybase::value_compare value_compare;
  typedef typename _Mybase::allocator_type allocator_type;
  typedef typename _Mybase::size_type size_type;
  typedef typename _Mybase::difference_type difference_type;
  typedef typename _Mybase::pointer pointer;
  typedef typename _Mybase::const_pointer const_pointer;
  typedef typename _Mybase::reference reference;
  typedef typename _Mybase::const_reference const_reference;
  typedef typename _Mybase::iterator iterator;
  typedef typename _Mybase::const_iterator const_iterator;
  typedef typename _Mybase::reverse_iterator reverse_iterator;
  typedef typename _Mybase::const_reverse_iterator
  const_reverse_iterator;
  typedef typename _Mybase::value_type value_type;

  hash_multiset()
  : _Mybase(key_compare(), allocator_type())
  {}      // construct empty set from defaults

  explicit hash_multiset(const key_compare& _Traits)
  : _Mybase(_Traits, allocator_type())
  {}      // construct empty set from comparator

  hash_multiset(const key_compare& _Traits,
                const allocator_type& _Al)
  : _Mybase(_Traits, _Al)
  {}      // construct empty set from comparator and allocator

  template<class _Iter>
  hash_multiset(_Iter _First, _Iter _Last)
  : _Mybase(key_compare(), allocator_type())
  {       // construct from sequence, defaults
    _Mybase::insert(_First, _Last);
  }

  template<class _Iter>
  hash_multiset(_Iter _First, _Iter _Last, const key_compare& _Traits)
  : _Mybase(_Traits, allocator_type())
  {       // construct from sequence, comparator
    _Mybase::insert(_First, _Last);
  }

  template<class _Iter>
  hash_multiset(_Iter _First, _Iter _Last, const key_compare& _Traits,
                const allocator_type& _Al)
  : _Mybase(_Traits, _Al)
  {       // construct from sequence, comparator, and allocator
    _Mybase::insert(_First, _Last);
  }

  iterator insert(const value_type& _Val)
  {       // insert a key value
    return (_Mybase::insert(_Val).first); 
  }

  iterator insert(iterator _Where, const value_type& _Val)
  {       // insert a key value, with hint
    return (_Mybase::insert(_Where, _Val)); 
  }

  template<class _Iter>
  _ALLOW_ONLY_ITERATORS(_Iter, void)
  insert(_Iter _First, _Iter _Last)
  {
    _Mybase::insert(_First, _Last);
  }
};
#pragma language = restore
_DLIB5_END
#endif /* _HASH_SET_ */

/*
 * Copyright (c) 1992-2009 by P.J. Plauger.  ALL RIGHTS RESERVED.
 * Consult your license regarding permissions and restrictions.
 V5.04:0576 */
