From 6ca4730897adeb7101cbfdc175151cb2e891cafb Mon Sep 17 00:00:00 2001
From: Brad King <brad.king@kitware.com>
Date: Wed, 13 Apr 2005 08:08:54 -0400
Subject: [PATCH] ENH: Adding SGI hash_map and hash_set implementation ported
 from STL to KWSys.  This also adds try-compiles for
 KWSYS_STL_HAS_ALLOCATOR_REBIND, KWSYS_CXX_HAS_FULL_SPECIALIZATION,
 KWSYS_CXX_HAS_MEMBER_TEMPLATES, and KWSYS_CXX_HAS_NULL_TEMPLATE_ARGS.

---
 CMakeLists.txt            |   15 +-
 Configure.hxx.in          |   39 ++
 hash_fun.hxx.in           |  115 ++++
 hash_map.hxx.in           |  475 ++++++++++++++++
 hash_set.hxx.in           |  459 ++++++++++++++++
 hashtable.hxx.in          | 1088 +++++++++++++++++++++++++++++++++++++
 kwsysPlatformCxxTests.cxx |   86 ++-
 testhash.cxx              |   51 ++
 8 files changed, 2311 insertions(+), 17 deletions(-)
 create mode 100644 hash_fun.hxx.in
 create mode 100644 hash_map.hxx.in
 create mode 100644 hash_set.hxx.in
 create mode 100644 hashtable.hxx.in
 create mode 100644 testhash.cxx

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 1ddc418a..df4e0d59 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -179,6 +179,8 @@ SET(KWSYS_PLATFORM_CXX_TEST_DEFINES
   -DKWSYS_STL_HAVE_STD=${KWSYS_STL_HAVE_STD})
 KWSYS_PLATFORM_CXX_TEST(KWSYS_STL_STRING_HAVE_NEQ_CHAR
   "Checking whether stl string has operator!= for char*" DIRECT)
+KWSYS_PLATFORM_CXX_TEST(KWSYS_STL_HAS_ALLOCATOR_REBIND
+  "Checking for rebind member of stl allocator" DIRECT)
 IF(KWSYS_IOS_USE_ANSI)
   # ANSI streams always have string operators.
   SET(KWSYS_STL_STRING_HAVE_OSTREAM 1)
@@ -192,6 +194,13 @@ ELSE(KWSYS_IOS_USE_ANSI)
 ENDIF(KWSYS_IOS_USE_ANSI)
 SET(KWSYS_PLATFORM_CXX_TEST_DEFINES)
 
+KWSYS_PLATFORM_CXX_TEST(KWSYS_CXX_HAS_NULL_TEMPLATE_ARGS
+  "Checking whether \"<>\" is needed for template friends" INVERT)
+KWSYS_PLATFORM_CXX_TEST(KWSYS_CXX_HAS_MEMBER_TEMPLATES
+  "Checking for member template support" DIRECT)
+KWSYS_PLATFORM_CXX_TEST(KWSYS_CXX_HAS_FULL_SPECIALIZATION
+  "Checking for standard template specialization syntax" DIRECT)
+
 IF(UNIX)
   KWSYS_PLATFORM_CXX_TEST(KWSYS_STAT_HAS_ST_MTIM
     "Checking whether struct stat has st_mtim member" DIRECT)
@@ -229,7 +238,7 @@ INCLUDE_DIRECTORIES(${KWSYS_HEADER_ROOT})
 # give standard names by which they may be included.
 SET(KWSYS_STL_HEADER_EXTRA_string 1)
 FOREACH(header algorithm deque iterator list map numeric queue set stack string
-               utility vector)
+               utility vector memory functional)
   # Configure the header wrapper.
   SET(KWSYS_STL_HEADER "${header}")
   IF(KWSYS_STL_HEADER_EXTRA_${header})
@@ -277,7 +286,7 @@ ENDFOREACH(header)
 # selected components.  Initialize with required components.
 SET(KWSYS_CLASSES)
 SET(KWSYS_H_FILES Configure SharedForward)
-SET(KWSYS_HXX_FILES Configure)
+SET(KWSYS_HXX_FILES Configure hashtable hash_fun hash_map hash_set)
 
 # Enforce component dependencies.
 IF(KWSYS_USE_SystemTools)
@@ -456,10 +465,12 @@ ENDIF(KWSYS_USE_Process)
 # Setup testing if not being built as part of another project.
 IF(KWSYS_STANDALONE)
   ADD_EXECUTABLE(testIOS testIOS.cxx)
+  ADD_EXECUTABLE(testhash testhash.cxx)
   ADD_EXECUTABLE(testProcess testProcess.c)
   ADD_EXECUTABLE(test1 test1.cxx)
   ADD_EXECUTABLE(testCommandLineArguments testCommandLineArguments.cxx)
   TARGET_LINK_LIBRARIES(testIOS ${KWSYS_NAMESPACE})
+  TARGET_LINK_LIBRARIES(testhash ${KWSYS_NAMESPACE})
   TARGET_LINK_LIBRARIES(testProcess ${KWSYS_NAMESPACE}_c)
   TARGET_LINK_LIBRARIES(test1 ${KWSYS_NAMESPACE})
   TARGET_LINK_LIBRARIES(testCommandLineArguments ${KWSYS_NAMESPACE})
diff --git a/Configure.hxx.in b/Configure.hxx.in
index d1c6d870..a9a35a82 100644
--- a/Configure.hxx.in
+++ b/Configure.hxx.in
@@ -63,6 +63,39 @@
 # define @KWSYS_NAMESPACE@_ios @KWSYS_NAMESPACE@_ios
 #endif
 
+/* Whether the compiler supports null template arguments.  */
+#define @KWSYS_NAMESPACE@_CXX_HAS_NULL_TEMPLATE_ARGS @KWSYS_CXX_HAS_NULL_TEMPLATE_ARGS@
+
+/* Define the null template arguments macro.  */
+#if @KWSYS_NAMESPACE@_CXX_HAS_NULL_TEMPLATE_ARGS
+# define @KWSYS_NAMESPACE@_CXX_NULL_TEMPLATE_ARGS <>
+#else
+# define @KWSYS_NAMESPACE@_CXX_NULL_TEMPLATE_ARGS
+#endif
+
+/* Whether the compiler supports member templates.  */
+#define @KWSYS_NAMESPACE@_CXX_HAS_MEMBER_TEMPLATES @KWSYS_CXX_HAS_MEMBER_TEMPLATES@
+
+/* Whether the compiler supports standard full specialization syntax.  */
+#define @KWSYS_NAMESPACE@_CXX_HAS_FULL_SPECIALIZATION @KWSYS_CXX_HAS_FULL_SPECIALIZATION@
+
+/* Define the specialization definition macro.  */
+#if @KWSYS_NAMESPACE@_CXX_HAS_FULL_SPECIALIZATION
+# define @KWSYS_NAMESPACE@_CXX_DEFINE_SPECIALIZATION template <>
+#else
+# define @KWSYS_NAMESPACE@_CXX_DEFINE_SPECIALIZATION
+#endif
+
+/* Define typename keyword macro for use in declarations.  */
+#if defined(_MSC_VER) && _MSC_VER < 1300
+# define @KWSYS_NAMESPACE@_CXX_DECL_TYPENAME
+#else
+# define @KWSYS_NAMESPACE@_CXX_DECL_TYPENAME typename
+#endif
+
+/* Whether the stl allocator has rebind.  */
+#define @KWSYS_NAMESPACE@_STL_HAS_ALLOCATOR_REBIND @KWSYS_STL_HAS_ALLOCATOR_REBIND@
+
 /* Whether struct stat has the st_mtim member for high resolution times.  */
 #define @KWSYS_NAMESPACE@_STAT_HAS_ST_MTIM @KWSYS_STAT_HAS_ST_MTIM@
 
@@ -84,6 +117,12 @@
 # define KWSYS_STL_STRING_HAVE_OSTREAM  @KWSYS_NAMESPACE@_STL_STRING_HAVE_OSTREAM
 # define KWSYS_STL_STRING_HAVE_ISTREAM  @KWSYS_NAMESPACE@_STL_STRING_HAVE_ISTREAM
 # define KWSYS_STL_STRING_HAVE_NEQ_CHAR @KWSYS_NAMESPACE@_STL_STRING_HAVE_NEQ_CHAR
+# define KWSYS_CXX_NULL_TEMPLATE_ARGS   @KWSYS_NAMESPACE@_CXX_NULL_TEMPLATE_ARGS
+# define KWSYS_CXX_HAS_MEMBER_TEMPLATES @KWSYS_NAMESPACE@_CXX_HAS_MEMBER_TEMPLATES
+# define KWSYS_CXX_HAS_FULL_SPECIALIZATION @KWSYS_NAMESPACE@_CXX_HAS_FULL_SPECIALIZATION
+# define KWSYS_CXX_DEFINE_SPECIALIZATION @KWSYS_NAMESPACE@_CXX_DEFINE_SPECIALIZATION
+# define KWSYS_CXX_DECL_TYPENAME        @KWSYS_NAMESPACE@_CXX_DECL_TYPENAME
+# define KWSYS_STL_HAS_ALLOCATOR_REBIND @KWSYS_NAMESPACE@_STL_HAS_ALLOCATOR_REBIND
 #endif
 
 #endif
diff --git a/hash_fun.hxx.in b/hash_fun.hxx.in
new file mode 100644
index 00000000..3cab9c75
--- /dev/null
+++ b/hash_fun.hxx.in
@@ -0,0 +1,115 @@
+/*=========================================================================
+
+  Program:   KWSys - Kitware System Library
+  Module:    hash_fun.hxx.in
+
+  Copyright (c) Kitware, Inc., Insight Consortium.  All rights reserved.
+  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
+
+     This software is distributed WITHOUT ANY WARRANTY; without even
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+     PURPOSE.  See the above copyright notices for more information.
+
+=========================================================================*/
+/*
+ * Copyright (c) 1996
+ * Silicon Graphics Computer Systems, Inc.
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.  Silicon Graphics makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ *
+ *
+ * Copyright (c) 1994
+ * Hewlett-Packard Company
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.  Hewlett-Packard Company makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ *
+ */
+#ifndef @KWSYS_NAMESPACE@_hash_fun_hxx
+#define @KWSYS_NAMESPACE@_hash_fun_hxx
+
+#include <@KWSYS_NAMESPACE@/Configure.hxx>
+
+namespace @KWSYS_NAMESPACE@
+{
+
+template <class _Key> struct hash { };
+
+inline size_t _stl_hash_string(const char* __s)
+{
+  unsigned long __h = 0;
+  for ( ; *__s; ++__s)
+    __h = 5*__h + *__s;
+
+  return size_t(__h);
+}
+
+@KWSYS_NAMESPACE@_CXX_DEFINE_SPECIALIZATION
+struct hash<char*> {
+  size_t operator()(const char* __s) const { return _stl_hash_string(__s); }
+};
+
+@KWSYS_NAMESPACE@_CXX_DEFINE_SPECIALIZATION
+struct hash<const char*> {
+  size_t operator()(const char* __s) const { return _stl_hash_string(__s); }
+};
+
+@KWSYS_NAMESPACE@_CXX_DEFINE_SPECIALIZATION
+struct hash<char> {
+  size_t operator()(char __x) const { return __x; }
+};
+
+@KWSYS_NAMESPACE@_CXX_DEFINE_SPECIALIZATION
+struct hash<unsigned char> {
+  size_t operator()(unsigned char __x) const { return __x; }
+};
+
+@KWSYS_NAMESPACE@_CXX_DEFINE_SPECIALIZATION
+struct hash<signed char> {
+  size_t operator()(unsigned char __x) const { return __x; }
+};
+
+@KWSYS_NAMESPACE@_CXX_DEFINE_SPECIALIZATION
+struct hash<short> {
+  size_t operator()(short __x) const { return __x; }
+};
+
+@KWSYS_NAMESPACE@_CXX_DEFINE_SPECIALIZATION
+struct hash<unsigned short> {
+  size_t operator()(unsigned short __x) const { return __x; }
+};
+
+@KWSYS_NAMESPACE@_CXX_DEFINE_SPECIALIZATION
+struct hash<int> {
+  size_t operator()(int __x) const { return __x; }
+};
+
+@KWSYS_NAMESPACE@_CXX_DEFINE_SPECIALIZATION
+struct hash<unsigned int> {
+  size_t operator()(unsigned int __x) const { return __x; }
+};
+
+@KWSYS_NAMESPACE@_CXX_DEFINE_SPECIALIZATION
+struct hash<long> {
+  size_t operator()(long __x) const { return __x; }
+};
+
+@KWSYS_NAMESPACE@_CXX_DEFINE_SPECIALIZATION
+struct hash<unsigned long> {
+  size_t operator()(unsigned long __x) const { return __x; }
+};
+
+} // namespace @KWSYS_NAMESPACE@
+
+#endif
diff --git a/hash_map.hxx.in b/hash_map.hxx.in
new file mode 100644
index 00000000..0fef8e0f
--- /dev/null
+++ b/hash_map.hxx.in
@@ -0,0 +1,475 @@
+/*=========================================================================
+
+  Program:   KWSys - Kitware System Library
+  Module:    hash_map.hxx.in
+
+  Copyright (c) Kitware, Inc., Insight Consortium.  All rights reserved.
+  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
+
+     This software is distributed WITHOUT ANY WARRANTY; without even
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+     PURPOSE.  See the above copyright notices for more information.
+
+=========================================================================*/
+/*
+ * Copyright (c) 1996
+ * Silicon Graphics Computer Systems, Inc.
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.  Silicon Graphics makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ *
+ *
+ * Copyright (c) 1994
+ * Hewlett-Packard Company
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.  Hewlett-Packard Company makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ *
+ */
+#ifndef @KWSYS_NAMESPACE@_hash_map_hxx
+#define @KWSYS_NAMESPACE@_hash_map_hxx
+
+#include <@KWSYS_NAMESPACE@/hashtable.hxx>
+#include <@KWSYS_NAMESPACE@/hash_fun.hxx>
+#include <@KWSYS_NAMESPACE@/stl/functional> // equal_to
+
+#if defined(_MSC_VER)
+# pragma warning (push)
+# pragma warning (disable:4284)
+# pragma warning (disable:4786)
+#endif
+
+#if defined(__sgi) && !defined(__GNUC__) && (_MIPS_SIM != _MIPS_SIM_ABI32)
+# pragma set woff 1174
+# pragma set woff 1375
+#endif
+
+namespace @KWSYS_NAMESPACE@
+{
+
+// select1st is an extension: it is not part of the standard.
+template <class _Pair>
+struct _Select1st : public kwsys_stl::unary_function<_Pair, typename _Pair::first_type>
+{
+  const typename _Pair::first_type& operator()(const _Pair& __x) const
+    { return __x.first; }
+};
+
+// Forward declaration of equality operator; needed for friend declaration.
+
+template <class _Key, class _Tp,
+          class _HashFcn  = hash<_Key>,
+          class _EqualKey = kwsys_stl::equal_to<_Key>,
+          class _Alloc =  kwsys_stl::allocator<char> >
+class hash_map;
+
+template <class _Key, class _Tp, class _HashFn, class _EqKey, class _Alloc>
+inline bool operator==(const hash_map<_Key, _Tp, _HashFn, _EqKey, _Alloc>&,
+                       const hash_map<_Key, _Tp, _HashFn, _EqKey, _Alloc>&);
+
+template <class _Key, class _Tp, class _HashFcn, class _EqualKey,
+          class _Alloc>
+class hash_map
+{
+private:
+  typedef hashtable<kwsys_stl::pair<const _Key,_Tp>,_Key,_HashFcn,
+                    _Select1st<kwsys_stl::pair<const _Key,_Tp> >,_EqualKey,_Alloc> _Ht;
+  _Ht _M_ht;
+
+public:
+  typedef typename _Ht::key_type key_type;
+  typedef _Tp data_type;
+  typedef _Tp mapped_type;
+  typedef typename _Ht::value_type value_type;
+  typedef typename _Ht::hasher hasher;
+  typedef typename _Ht::key_equal key_equal;
+
+  typedef typename _Ht::size_type size_type;
+  typedef typename _Ht::difference_type difference_type;
+  typedef typename _Ht::pointer pointer;
+  typedef typename _Ht::const_pointer const_pointer;
+  typedef typename _Ht::reference reference;
+  typedef typename _Ht::const_reference const_reference;
+
+  typedef typename _Ht::iterator iterator;
+  typedef typename _Ht::const_iterator const_iterator;
+
+  typedef typename _Ht::allocator_type allocator_type;
+
+  hasher hash_funct() const { return _M_ht.hash_funct(); }
+  key_equal key_eq() const { return _M_ht.key_eq(); }
+  allocator_type get_allocator() const { return _M_ht.get_allocator(); }
+
+public:
+  hash_map() : _M_ht(100, hasher(), key_equal(), allocator_type()) {}
+  explicit hash_map(size_type __n)
+    : _M_ht(__n, hasher(), key_equal(), allocator_type()) {}
+  hash_map(size_type __n, const hasher& __hf)
+    : _M_ht(__n, __hf, key_equal(), allocator_type()) {}
+  hash_map(size_type __n, const hasher& __hf, const key_equal& __eql,
+           const allocator_type& __a = allocator_type())
+    : _M_ht(__n, __hf, __eql, __a) {}
+
+#if @KWSYS_NAMESPACE@_CXX_HAS_MEMBER_TEMPLATES
+  template <class _InputIterator>
+  hash_map(_InputIterator __f, _InputIterator __l)
+    : _M_ht(100, hasher(), key_equal(), allocator_type())
+    { _M_ht.insert_unique(__f, __l); }
+  template <class _InputIterator>
+  hash_map(_InputIterator __f, _InputIterator __l, size_type __n)
+    : _M_ht(__n, hasher(), key_equal(), allocator_type())
+    { _M_ht.insert_unique(__f, __l); }
+  template <class _InputIterator>
+  hash_map(_InputIterator __f, _InputIterator __l, size_type __n,
+           const hasher& __hf)
+    : _M_ht(__n, __hf, key_equal(), allocator_type())
+    { _M_ht.insert_unique(__f, __l); }
+  template <class _InputIterator>
+  hash_map(_InputIterator __f, _InputIterator __l, size_type __n,
+           const hasher& __hf, const key_equal& __eql,
+           const allocator_type& __a = allocator_type())
+    : _M_ht(__n, __hf, __eql, __a)
+    { _M_ht.insert_unique(__f, __l); }
+
+#else
+  hash_map(const value_type* __f, const value_type* __l)
+    : _M_ht(100, hasher(), key_equal(), allocator_type())
+    { _M_ht.insert_unique(__f, __l); }
+  hash_map(const value_type* __f, const value_type* __l, size_type __n)
+    : _M_ht(__n, hasher(), key_equal(), allocator_type())
+    { _M_ht.insert_unique(__f, __l); }
+  hash_map(const value_type* __f, const value_type* __l, size_type __n,
+           const hasher& __hf)
+    : _M_ht(__n, __hf, key_equal(), allocator_type())
+    { _M_ht.insert_unique(__f, __l); }
+  hash_map(const value_type* __f, const value_type* __l, size_type __n,
+           const hasher& __hf, const key_equal& __eql,
+           const allocator_type& __a = allocator_type())
+    : _M_ht(__n, __hf, __eql, __a)
+    { _M_ht.insert_unique(__f, __l); }
+
+  hash_map(const_iterator __f, const_iterator __l)
+    : _M_ht(100, hasher(), key_equal(), allocator_type())
+    { _M_ht.insert_unique(__f, __l); }
+  hash_map(const_iterator __f, const_iterator __l, size_type __n)
+    : _M_ht(__n, hasher(), key_equal(), allocator_type())
+    { _M_ht.insert_unique(__f, __l); }
+  hash_map(const_iterator __f, const_iterator __l, size_type __n,
+           const hasher& __hf)
+    : _M_ht(__n, __hf, key_equal(), allocator_type())
+    { _M_ht.insert_unique(__f, __l); }
+  hash_map(const_iterator __f, const_iterator __l, size_type __n,
+           const hasher& __hf, const key_equal& __eql,
+           const allocator_type& __a = allocator_type())
+    : _M_ht(__n, __hf, __eql, __a)
+    { _M_ht.insert_unique(__f, __l); }
+#endif
+
+public:
+  size_type size() const { return _M_ht.size(); }
+  size_type max_size() const { return _M_ht.max_size(); }
+  bool empty() const { return _M_ht.empty(); }
+  void swap(hash_map& __hs) { _M_ht.swap(__hs._M_ht); }
+
+#if @KWSYS_NAMESPACE@_CXX_HAS_MEMBER_TEMPLATES
+  template <class _K1, class _T1, class _HF, class _EqK, class _Al>
+  friend bool operator== (const hash_map<_K1, _T1, _HF, _EqK, _Al>&,
+                          const hash_map<_K1, _T1, _HF, _EqK, _Al>&);
+#else
+  friend bool operator==@KWSYS_NAMESPACE@_CXX_NULL_TEMPLATE_ARGS(const hash_map&,
+                                                                 const hash_map&);
+#endif
+
+
+  iterator begin() { return _M_ht.begin(); }
+  iterator end() { return _M_ht.end(); }
+  const_iterator begin() const { return _M_ht.begin(); }
+  const_iterator end() const { return _M_ht.end(); }
+
+public:
+  kwsys_stl::pair<iterator,bool> insert(const value_type& __obj)
+    { return _M_ht.insert_unique(__obj); }
+#if @KWSYS_NAMESPACE@_CXX_HAS_MEMBER_TEMPLATES
+  template <class _InputIterator>
+  void insert(_InputIterator __f, _InputIterator __l)
+    { _M_ht.insert_unique(__f,__l); }
+#else
+  void insert(const value_type* __f, const value_type* __l) {
+    _M_ht.insert_unique(__f,__l);
+  }
+  void insert(const_iterator __f, const_iterator __l)
+    { _M_ht.insert_unique(__f, __l); }
+#endif
+  kwsys_stl::pair<iterator,bool> insert_noresize(const value_type& __obj)
+    { return _M_ht.insert_unique_noresize(__obj); }
+
+  iterator find(const key_type& __key) { return _M_ht.find(__key); }
+  const_iterator find(const key_type& __key) const
+    { return _M_ht.find(__key); }
+
+  _Tp& operator[](const key_type& __key) {
+    return _M_ht.find_or_insert(value_type(__key, _Tp())).second;
+  }
+
+  size_type count(const key_type& __key) const { return _M_ht.count(__key); }
+
+  kwsys_stl::pair<iterator, iterator> equal_range(const key_type& __key)
+    { return _M_ht.equal_range(__key); }
+  kwsys_stl::pair<const_iterator, const_iterator>
+  equal_range(const key_type& __key) const
+    { return _M_ht.equal_range(__key); }
+
+  size_type erase(const key_type& __key) {return _M_ht.erase(__key); }
+  void erase(iterator __it) { _M_ht.erase(__it); }
+  void erase(iterator __f, iterator __l) { _M_ht.erase(__f, __l); }
+  void clear() { _M_ht.clear(); }
+
+  void resize(size_type __hint) { _M_ht.resize(__hint); }
+  size_type bucket_count() const { return _M_ht.bucket_count(); }
+  size_type max_bucket_count() const { return _M_ht.max_bucket_count(); }
+  size_type elems_in_bucket(size_type __n) const
+    { return _M_ht.elems_in_bucket(__n); }
+};
+
+template <class _Key, class _Tp, class _HashFcn, class _EqlKey, class _Alloc>
+inline bool
+operator==(const hash_map<_Key,_Tp,_HashFcn,_EqlKey,_Alloc>& __hm1,
+           const hash_map<_Key,_Tp,_HashFcn,_EqlKey,_Alloc>& __hm2)
+{
+  return __hm1._M_ht == __hm2._M_ht;
+}
+
+template <class _Key, class _Tp, class _HashFcn, class _EqlKey, class _Alloc>
+inline bool
+operator!=(const hash_map<_Key,_Tp,_HashFcn,_EqlKey,_Alloc>& __hm1,
+           const hash_map<_Key,_Tp,_HashFcn,_EqlKey,_Alloc>& __hm2) {
+  return !(__hm1 == __hm2);
+}
+
+template <class _Key, class _Tp, class _HashFcn, class _EqlKey, class _Alloc>
+inline void
+swap(hash_map<_Key,_Tp,_HashFcn,_EqlKey,_Alloc>& __hm1,
+     hash_map<_Key,_Tp,_HashFcn,_EqlKey,_Alloc>& __hm2)
+{
+  __hm1.swap(__hm2);
+}
+
+// Forward declaration of equality operator; needed for friend declaration.
+
+template <class _Key, class _Tp,
+          class _HashFcn  = hash<_Key>,
+          class _EqualKey = kwsys_stl::equal_to<_Key>,
+          class _Alloc =  kwsys_stl::allocator<char> >
+class hash_multimap;
+
+template <class _Key, class _Tp, class _HF, class _EqKey, class _Alloc>
+inline bool
+operator==(const hash_multimap<_Key,_Tp,_HF,_EqKey,_Alloc>& __hm1,
+           const hash_multimap<_Key,_Tp,_HF,_EqKey,_Alloc>& __hm2);
+
+template <class _Key, class _Tp, class _HashFcn, class _EqualKey,
+          class _Alloc>
+class hash_multimap
+{
+private:
+  typedef hashtable<kwsys_stl::pair<const _Key, _Tp>, _Key, _HashFcn,
+                    _Select1st<kwsys_stl::pair<const _Key, _Tp> >, _EqualKey, _Alloc>
+          _Ht;
+  _Ht _M_ht;
+
+public:
+  typedef typename _Ht::key_type key_type;
+  typedef _Tp data_type;
+  typedef _Tp mapped_type;
+  typedef typename _Ht::value_type value_type;
+  typedef typename _Ht::hasher hasher;
+  typedef typename _Ht::key_equal key_equal;
+
+  typedef typename _Ht::size_type size_type;
+  typedef typename _Ht::difference_type difference_type;
+  typedef typename _Ht::pointer pointer;
+  typedef typename _Ht::const_pointer const_pointer;
+  typedef typename _Ht::reference reference;
+  typedef typename _Ht::const_reference const_reference;
+
+  typedef typename _Ht::iterator iterator;
+  typedef typename _Ht::const_iterator const_iterator;
+
+  typedef typename _Ht::allocator_type allocator_type;
+
+  hasher hash_funct() const { return _M_ht.hash_funct(); }
+  key_equal key_eq() const { return _M_ht.key_eq(); }
+  allocator_type get_allocator() const { return _M_ht.get_allocator(); }
+
+public:
+  hash_multimap() : _M_ht(100, hasher(), key_equal(), allocator_type()) {}
+  explicit hash_multimap(size_type __n)
+    : _M_ht(__n, hasher(), key_equal(), allocator_type()) {}
+  hash_multimap(size_type __n, const hasher& __hf)
+    : _M_ht(__n, __hf, key_equal(), allocator_type()) {}
+  hash_multimap(size_type __n, const hasher& __hf, const key_equal& __eql,
+                const allocator_type& __a = allocator_type())
+    : _M_ht(__n, __hf, __eql, __a) {}
+
+#if @KWSYS_NAMESPACE@_CXX_HAS_MEMBER_TEMPLATES
+  template <class _InputIterator>
+  hash_multimap(_InputIterator __f, _InputIterator __l)
+    : _M_ht(100, hasher(), key_equal(), allocator_type())
+    { _M_ht.insert_equal(__f, __l); }
+  template <class _InputIterator>
+  hash_multimap(_InputIterator __f, _InputIterator __l, size_type __n)
+    : _M_ht(__n, hasher(), key_equal(), allocator_type())
+    { _M_ht.insert_equal(__f, __l); }
+  template <class _InputIterator>
+  hash_multimap(_InputIterator __f, _InputIterator __l, size_type __n,
+                const hasher& __hf)
+    : _M_ht(__n, __hf, key_equal(), allocator_type())
+    { _M_ht.insert_equal(__f, __l); }
+  template <class _InputIterator>
+  hash_multimap(_InputIterator __f, _InputIterator __l, size_type __n,
+                const hasher& __hf, const key_equal& __eql,
+                const allocator_type& __a = allocator_type())
+    : _M_ht(__n, __hf, __eql, __a)
+    { _M_ht.insert_equal(__f, __l); }
+
+#else
+  hash_multimap(const value_type* __f, const value_type* __l)
+    : _M_ht(100, hasher(), key_equal(), allocator_type())
+    { _M_ht.insert_equal(__f, __l); }
+  hash_multimap(const value_type* __f, const value_type* __l, size_type __n)
+    : _M_ht(__n, hasher(), key_equal(), allocator_type())
+    { _M_ht.insert_equal(__f, __l); }
+  hash_multimap(const value_type* __f, const value_type* __l, size_type __n,
+                const hasher& __hf)
+    : _M_ht(__n, __hf, key_equal(), allocator_type())
+    { _M_ht.insert_equal(__f, __l); }
+  hash_multimap(const value_type* __f, const value_type* __l, size_type __n,
+                const hasher& __hf, const key_equal& __eql,
+                const allocator_type& __a = allocator_type())
+    : _M_ht(__n, __hf, __eql, __a)
+    { _M_ht.insert_equal(__f, __l); }
+
+  hash_multimap(const_iterator __f, const_iterator __l)
+    : _M_ht(100, hasher(), key_equal(), allocator_type())
+    { _M_ht.insert_equal(__f, __l); }
+  hash_multimap(const_iterator __f, const_iterator __l, size_type __n)
+    : _M_ht(__n, hasher(), key_equal(), allocator_type())
+    { _M_ht.insert_equal(__f, __l); }
+  hash_multimap(const_iterator __f, const_iterator __l, size_type __n,
+                const hasher& __hf)
+    : _M_ht(__n, __hf, key_equal(), allocator_type())
+    { _M_ht.insert_equal(__f, __l); }
+  hash_multimap(const_iterator __f, const_iterator __l, size_type __n,
+                const hasher& __hf, const key_equal& __eql,
+                const allocator_type& __a = allocator_type())
+    : _M_ht(__n, __hf, __eql, __a)
+    { _M_ht.insert_equal(__f, __l); }
+#endif
+
+public:
+  size_type size() const { return _M_ht.size(); }
+  size_type max_size() const { return _M_ht.max_size(); }
+  bool empty() const { return _M_ht.empty(); }
+  void swap(hash_multimap& __hs) { _M_ht.swap(__hs._M_ht); }
+
+#if @KWSYS_NAMESPACE@_CXX_HAS_MEMBER_TEMPLATES
+  template <class _K1, class _T1, class _HF, class _EqK, class _Al>
+  friend bool operator== (const hash_multimap<_K1, _T1, _HF, _EqK, _Al>&,
+                          const hash_multimap<_K1, _T1, _HF, _EqK, _Al>&);
+#else
+  friend bool operator==@KWSYS_NAMESPACE@_CXX_NULL_TEMPLATE_ARGS(const hash_multimap&,
+                                                                 const hash_multimap&);
+#endif
+
+  iterator begin() { return _M_ht.begin(); }
+  iterator end() { return _M_ht.end(); }
+  const_iterator begin() const { return _M_ht.begin(); }
+  const_iterator end() const { return _M_ht.end(); }
+
+public:
+  iterator insert(const value_type& __obj)
+    { return _M_ht.insert_equal(__obj); }
+#if @KWSYS_NAMESPACE@_CXX_HAS_MEMBER_TEMPLATES
+  template <class _InputIterator>
+  void insert(_InputIterator __f, _InputIterator __l)
+    { _M_ht.insert_equal(__f,__l); }
+#else
+  void insert(const value_type* __f, const value_type* __l) {
+    _M_ht.insert_equal(__f,__l);
+  }
+  void insert(const_iterator __f, const_iterator __l)
+    { _M_ht.insert_equal(__f, __l); }
+#endif
+  iterator insert_noresize(const value_type& __obj)
+    { return _M_ht.insert_equal_noresize(__obj); }
+
+  iterator find(const key_type& __key) { return _M_ht.find(__key); }
+  const_iterator find(const key_type& __key) const
+    { return _M_ht.find(__key); }
+
+  size_type count(const key_type& __key) const { return _M_ht.count(__key); }
+
+  kwsys_stl::pair<iterator, iterator> equal_range(const key_type& __key)
+    { return _M_ht.equal_range(__key); }
+  kwsys_stl::pair<const_iterator, const_iterator>
+  equal_range(const key_type& __key) const
+    { return _M_ht.equal_range(__key); }
+
+  size_type erase(const key_type& __key) {return _M_ht.erase(__key); }
+  void erase(iterator __it) { _M_ht.erase(__it); }
+  void erase(iterator __f, iterator __l) { _M_ht.erase(__f, __l); }
+  void clear() { _M_ht.clear(); }
+
+public:
+  void resize(size_type __hint) { _M_ht.resize(__hint); }
+  size_type bucket_count() const { return _M_ht.bucket_count(); }
+  size_type max_bucket_count() const { return _M_ht.max_bucket_count(); }
+  size_type elems_in_bucket(size_type __n) const
+    { return _M_ht.elems_in_bucket(__n); }
+};
+
+template <class _Key, class _Tp, class _HF, class _EqKey, class _Alloc>
+inline bool
+operator==(const hash_multimap<_Key,_Tp,_HF,_EqKey,_Alloc>& __hm1,
+           const hash_multimap<_Key,_Tp,_HF,_EqKey,_Alloc>& __hm2)
+{
+  return __hm1._M_ht == __hm2._M_ht;
+}
+
+template <class _Key, class _Tp, class _HF, class _EqKey, class _Alloc>
+inline bool
+operator!=(const hash_multimap<_Key,_Tp,_HF,_EqKey,_Alloc>& __hm1,
+           const hash_multimap<_Key,_Tp,_HF,_EqKey,_Alloc>& __hm2) {
+  return !(__hm1 == __hm2);
+}
+
+template <class _Key, class _Tp, class _HashFcn, class _EqlKey, class _Alloc>
+inline void
+swap(hash_multimap<_Key,_Tp,_HashFcn,_EqlKey,_Alloc>& __hm1,
+     hash_multimap<_Key,_Tp,_HashFcn,_EqlKey,_Alloc>& __hm2)
+{
+  __hm1.swap(__hm2);
+}
+
+} // namespace @KWSYS_NAMESPACE@
+
+#if defined(__sgi) && !defined(__GNUC__) && (_MIPS_SIM != _MIPS_SIM_ABI32)
+# pragma reset woff 1174
+# pragma reset woff 1375
+#endif
+
+#if defined(_MSC_VER)
+# pragma warning (pop)
+#endif
+
+#endif
diff --git a/hash_set.hxx.in b/hash_set.hxx.in
new file mode 100644
index 00000000..42f4cc54
--- /dev/null
+++ b/hash_set.hxx.in
@@ -0,0 +1,459 @@
+/*=========================================================================
+
+  Program:   KWSys - Kitware System Library
+  Module:    hash_set.hxx.in
+
+  Copyright (c) Kitware, Inc., Insight Consortium.  All rights reserved.
+  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
+
+     This software is distributed WITHOUT ANY WARRANTY; without even
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+     PURPOSE.  See the above copyright notices for more information.
+
+=========================================================================*/
+/*
+ * Copyright (c) 1996
+ * Silicon Graphics Computer Systems, Inc.
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.  Silicon Graphics makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ *
+ *
+ * Copyright (c) 1994
+ * Hewlett-Packard Company
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.  Hewlett-Packard Company makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ *
+ */
+#ifndef @KWSYS_NAMESPACE@_hash_set_hxx
+#define @KWSYS_NAMESPACE@_hash_set_hxx
+
+#include <@KWSYS_NAMESPACE@/hashtable.hxx>
+#include <@KWSYS_NAMESPACE@/hash_fun.hxx>
+#include <@KWSYS_NAMESPACE@/stl/functional> // equal_to
+
+#if defined(_MSC_VER)
+# pragma warning (push)
+# pragma warning (disable:4284)
+# pragma warning (disable:4786)
+#endif
+
+#if defined(__sgi) && !defined(__GNUC__) && (_MIPS_SIM != _MIPS_SIM_ABI32)
+# pragma set woff 1174
+# pragma set woff 1375
+#endif
+
+namespace @KWSYS_NAMESPACE@
+{
+
+// identity is an extension: it is not part of the standard.
+template <class _Tp>
+struct _Identity : public kwsys_stl::unary_function<_Tp,_Tp>
+{
+  const _Tp& operator()(const _Tp& __x) const { return __x; }
+};
+
+// Forward declaration of equality operator; needed for friend declaration.
+
+template <class _Value,
+          class _HashFcn  = hash<_Value>,
+          class _EqualKey = kwsys_stl::equal_to<_Value>,
+          class _Alloc =  kwsys_stl::allocator<char> >
+class hash_set;
+
+template <class _Value, class _HashFcn, class _EqualKey, class _Alloc>
+inline bool
+operator==(const hash_set<_Value,_HashFcn,_EqualKey,_Alloc>& __hs1,
+           const hash_set<_Value,_HashFcn,_EqualKey,_Alloc>& __hs2);
+
+template <class _Value, class _HashFcn, class _EqualKey, class _Alloc>
+class hash_set
+{
+private:
+  typedef hashtable<_Value, _Value, _HashFcn, _Identity<_Value>,
+                    _EqualKey, _Alloc> _Ht;
+  _Ht _M_ht;
+
+public:
+  typedef typename _Ht::key_type key_type;
+  typedef typename _Ht::value_type value_type;
+  typedef typename _Ht::hasher hasher;
+  typedef typename _Ht::key_equal key_equal;
+
+  typedef typename _Ht::size_type size_type;
+  typedef typename _Ht::difference_type difference_type;
+  typedef typename _Ht::const_pointer pointer;
+  typedef typename _Ht::const_pointer const_pointer;
+  typedef typename _Ht::const_reference reference;
+  typedef typename _Ht::const_reference const_reference;
+
+  typedef typename _Ht::const_iterator iterator;
+  typedef typename _Ht::const_iterator const_iterator;
+
+  typedef typename _Ht::allocator_type allocator_type;
+
+  hasher hash_funct() const { return _M_ht.hash_funct(); }
+  key_equal key_eq() const { return _M_ht.key_eq(); }
+  allocator_type get_allocator() const { return _M_ht.get_allocator(); }
+
+public:
+  hash_set()
+    : _M_ht(100, hasher(), key_equal(), allocator_type()) {}
+  explicit hash_set(size_type __n)
+    : _M_ht(__n, hasher(), key_equal(), allocator_type()) {}
+  hash_set(size_type __n, const hasher& __hf)
+    : _M_ht(__n, __hf, key_equal(), allocator_type()) {}
+  hash_set(size_type __n, const hasher& __hf, const key_equal& __eql,
+           const allocator_type& __a = allocator_type())
+    : _M_ht(__n, __hf, __eql, __a) {}
+
+#if @KWSYS_NAMESPACE@_CXX_HAS_MEMBER_TEMPLATES
+  template <class _InputIterator>
+  hash_set(_InputIterator __f, _InputIterator __l)
+    : _M_ht(100, hasher(), key_equal(), allocator_type())
+    { _M_ht.insert_unique(__f, __l); }
+  template <class _InputIterator>
+  hash_set(_InputIterator __f, _InputIterator __l, size_type __n)
+    : _M_ht(__n, hasher(), key_equal(), allocator_type())
+    { _M_ht.insert_unique(__f, __l); }
+  template <class _InputIterator>
+  hash_set(_InputIterator __f, _InputIterator __l, size_type __n,
+           const hasher& __hf)
+    : _M_ht(__n, __hf, key_equal(), allocator_type())
+    { _M_ht.insert_unique(__f, __l); }
+  template <class _InputIterator>
+  hash_set(_InputIterator __f, _InputIterator __l, size_type __n,
+           const hasher& __hf, const key_equal& __eql,
+           const allocator_type& __a = allocator_type())
+    : _M_ht(__n, __hf, __eql, __a)
+    { _M_ht.insert_unique(__f, __l); }
+#else
+
+  hash_set(const value_type* __f, const value_type* __l)
+    : _M_ht(100, hasher(), key_equal(), allocator_type())
+    { _M_ht.insert_unique(__f, __l); }
+  hash_set(const value_type* __f, const value_type* __l, size_type __n)
+    : _M_ht(__n, hasher(), key_equal(), allocator_type())
+    { _M_ht.insert_unique(__f, __l); }
+  hash_set(const value_type* __f, const value_type* __l, size_type __n,
+           const hasher& __hf)
+    : _M_ht(__n, __hf, key_equal(), allocator_type())
+    { _M_ht.insert_unique(__f, __l); }
+  hash_set(const value_type* __f, const value_type* __l, size_type __n,
+           const hasher& __hf, const key_equal& __eql,
+           const allocator_type& __a = allocator_type())
+    : _M_ht(__n, __hf, __eql, __a)
+    { _M_ht.insert_unique(__f, __l); }
+
+  hash_set(const_iterator __f, const_iterator __l)
+    : _M_ht(100, hasher(), key_equal(), allocator_type())
+    { _M_ht.insert_unique(__f, __l); }
+  hash_set(const_iterator __f, const_iterator __l, size_type __n)
+    : _M_ht(__n, hasher(), key_equal(), allocator_type())
+    { _M_ht.insert_unique(__f, __l); }
+  hash_set(const_iterator __f, const_iterator __l, size_type __n,
+           const hasher& __hf)
+    : _M_ht(__n, __hf, key_equal(), allocator_type())
+    { _M_ht.insert_unique(__f, __l); }
+  hash_set(const_iterator __f, const_iterator __l, size_type __n,
+           const hasher& __hf, const key_equal& __eql,
+           const allocator_type& __a = allocator_type())
+    : _M_ht(__n, __hf, __eql, __a)
+    { _M_ht.insert_unique(__f, __l); }
+#endif
+
+public:
+  size_type size() const { return _M_ht.size(); }
+  size_type max_size() const { return _M_ht.max_size(); }
+  bool empty() const { return _M_ht.empty(); }
+  void swap(hash_set& __hs) { _M_ht.swap(__hs._M_ht); }
+
+#if @KWSYS_NAMESPACE@_CXX_HAS_MEMBER_TEMPLATES
+  template <class _Val, class _HF, class _EqK, class _Al>
+  friend bool operator== (const hash_set<_Val, _HF, _EqK, _Al>&,
+                          const hash_set<_Val, _HF, _EqK, _Al>&);
+#else
+  friend bool operator==@KWSYS_NAMESPACE@_CXX_NULL_TEMPLATE_ARGS(const hash_set&,
+                                                                 const hash_set&);
+#endif
+
+  iterator begin() const { return _M_ht.begin(); }
+  iterator end() const { return _M_ht.end(); }
+
+public:
+  kwsys_stl::pair<iterator, bool> insert(const value_type& __obj)
+    {
+      typedef typename _Ht::iterator _Ht_iterator;
+      kwsys_stl::pair<_Ht_iterator, bool> __p = _M_ht.insert_unique(__obj);
+      return kwsys_stl::pair<iterator,bool>(__p.first, __p.second);
+    }
+#if @KWSYS_NAMESPACE@_CXX_HAS_MEMBER_TEMPLATES
+  template <class _InputIterator>
+  void insert(_InputIterator __f, _InputIterator __l)
+    { _M_ht.insert_unique(__f,__l); }
+#else
+  void insert(const value_type* __f, const value_type* __l) {
+    _M_ht.insert_unique(__f,__l);
+  }
+  void insert(const_iterator __f, const_iterator __l)
+    {_M_ht.insert_unique(__f, __l); }
+#endif
+  kwsys_stl::pair<iterator, bool> insert_noresize(const value_type& __obj)
+  {
+    typedef typename _Ht::iterator _Ht_iterator;
+    kwsys_stl::pair<_Ht_iterator, bool> __p =
+      _M_ht.insert_unique_noresize(__obj);
+    return kwsys_stl::pair<iterator, bool>(__p.first, __p.second);
+  }
+
+  iterator find(const key_type& __key) const { return _M_ht.find(__key); }
+
+  size_type count(const key_type& __key) const { return _M_ht.count(__key); }
+
+  kwsys_stl::pair<iterator, iterator> equal_range(const key_type& __key) const
+    { return _M_ht.equal_range(__key); }
+
+  size_type erase(const key_type& __key) {return _M_ht.erase(__key); }
+  void erase(iterator __it) { _M_ht.erase(__it); }
+  void erase(iterator __f, iterator __l) { _M_ht.erase(__f, __l); }
+  void clear() { _M_ht.clear(); }
+
+public:
+  void resize(size_type __hint) { _M_ht.resize(__hint); }
+  size_type bucket_count() const { return _M_ht.bucket_count(); }
+  size_type max_bucket_count() const { return _M_ht.max_bucket_count(); }
+  size_type elems_in_bucket(size_type __n) const
+    { return _M_ht.elems_in_bucket(__n); }
+};
+
+template <class _Value, class _HashFcn, class _EqualKey, class _Alloc>
+inline bool
+operator==(const hash_set<_Value,_HashFcn,_EqualKey,_Alloc>& __hs1,
+           const hash_set<_Value,_HashFcn,_EqualKey,_Alloc>& __hs2)
+{
+  return __hs1._M_ht == __hs2._M_ht;
+}
+
+template <class _Value, class _HashFcn, class _EqualKey, class _Alloc>
+inline bool
+operator!=(const hash_set<_Value,_HashFcn,_EqualKey,_Alloc>& __hs1,
+           const hash_set<_Value,_HashFcn,_EqualKey,_Alloc>& __hs2) {
+  return !(__hs1 == __hs2);
+}
+
+template <class _Val, class _HashFcn, class _EqualKey, class _Alloc>
+inline void
+swap(hash_set<_Val,_HashFcn,_EqualKey,_Alloc>& __hs1,
+     hash_set<_Val,_HashFcn,_EqualKey,_Alloc>& __hs2)
+{
+  __hs1.swap(__hs2);
+}
+
+template <class _Value,
+          class _HashFcn = hash<_Value>,
+          class _EqualKey = kwsys_stl::equal_to<_Value>,
+          class _Alloc =  kwsys_stl::allocator<char> >
+class hash_multiset;
+
+template <class _Val, class _HashFcn, class _EqualKey, class _Alloc>
+inline bool
+operator==(const hash_multiset<_Val,_HashFcn,_EqualKey,_Alloc>& __hs1,
+           const hash_multiset<_Val,_HashFcn,_EqualKey,_Alloc>& __hs2);
+
+
+template <class _Value, class _HashFcn, class _EqualKey, class _Alloc>
+class hash_multiset
+{
+private:
+  typedef hashtable<_Value, _Value, _HashFcn, _Identity<_Value>,
+                    _EqualKey, _Alloc> _Ht;
+  _Ht _M_ht;
+
+public:
+  typedef typename _Ht::key_type key_type;
+  typedef typename _Ht::value_type value_type;
+  typedef typename _Ht::hasher hasher;
+  typedef typename _Ht::key_equal key_equal;
+
+  typedef typename _Ht::size_type size_type;
+  typedef typename _Ht::difference_type difference_type;
+  typedef typename _Ht::const_pointer pointer;
+  typedef typename _Ht::const_pointer const_pointer;
+  typedef typename _Ht::const_reference reference;
+  typedef typename _Ht::const_reference const_reference;
+
+  typedef typename _Ht::const_iterator iterator;
+  typedef typename _Ht::const_iterator const_iterator;
+
+  typedef typename _Ht::allocator_type allocator_type;
+
+  hasher hash_funct() const { return _M_ht.hash_funct(); }
+  key_equal key_eq() const { return _M_ht.key_eq(); }
+  allocator_type get_allocator() const { return _M_ht.get_allocator(); }
+
+public:
+  hash_multiset()
+    : _M_ht(100, hasher(), key_equal(), allocator_type()) {}
+  explicit hash_multiset(size_type __n)
+    : _M_ht(__n, hasher(), key_equal(), allocator_type()) {}
+  hash_multiset(size_type __n, const hasher& __hf)
+    : _M_ht(__n, __hf, key_equal(), allocator_type()) {}
+  hash_multiset(size_type __n, const hasher& __hf, const key_equal& __eql,
+                const allocator_type& __a = allocator_type())
+    : _M_ht(__n, __hf, __eql, __a) {}
+
+#if @KWSYS_NAMESPACE@_CXX_HAS_MEMBER_TEMPLATES
+  template <class _InputIterator>
+  hash_multiset(_InputIterator __f, _InputIterator __l)
+    : _M_ht(100, hasher(), key_equal(), allocator_type())
+    { _M_ht.insert_equal(__f, __l); }
+  template <class _InputIterator>
+  hash_multiset(_InputIterator __f, _InputIterator __l, size_type __n)
+    : _M_ht(__n, hasher(), key_equal(), allocator_type())
+    { _M_ht.insert_equal(__f, __l); }
+  template <class _InputIterator>
+  hash_multiset(_InputIterator __f, _InputIterator __l, size_type __n,
+                const hasher& __hf)
+    : _M_ht(__n, __hf, key_equal(), allocator_type())
+    { _M_ht.insert_equal(__f, __l); }
+  template <class _InputIterator>
+  hash_multiset(_InputIterator __f, _InputIterator __l, size_type __n,
+                const hasher& __hf, const key_equal& __eql,
+                const allocator_type& __a = allocator_type())
+    : _M_ht(__n, __hf, __eql, __a)
+    { _M_ht.insert_equal(__f, __l); }
+#else
+
+  hash_multiset(const value_type* __f, const value_type* __l)
+    : _M_ht(100, hasher(), key_equal(), allocator_type())
+    { _M_ht.insert_equal(__f, __l); }
+  hash_multiset(const value_type* __f, const value_type* __l, size_type __n)
+    : _M_ht(__n, hasher(), key_equal(), allocator_type())
+    { _M_ht.insert_equal(__f, __l); }
+  hash_multiset(const value_type* __f, const value_type* __l, size_type __n,
+                const hasher& __hf)
+    : _M_ht(__n, __hf, key_equal(), allocator_type())
+    { _M_ht.insert_equal(__f, __l); }
+  hash_multiset(const value_type* __f, const value_type* __l, size_type __n,
+                const hasher& __hf, const key_equal& __eql,
+                const allocator_type& __a = allocator_type())
+    : _M_ht(__n, __hf, __eql, __a)
+    { _M_ht.insert_equal(__f, __l); }
+
+  hash_multiset(const_iterator __f, const_iterator __l)
+    : _M_ht(100, hasher(), key_equal(), allocator_type())
+    { _M_ht.insert_equal(__f, __l); }
+  hash_multiset(const_iterator __f, const_iterator __l, size_type __n)
+    : _M_ht(__n, hasher(), key_equal(), allocator_type())
+    { _M_ht.insert_equal(__f, __l); }
+  hash_multiset(const_iterator __f, const_iterator __l, size_type __n,
+                const hasher& __hf)
+    : _M_ht(__n, __hf, key_equal(), allocator_type())
+    { _M_ht.insert_equal(__f, __l); }
+  hash_multiset(const_iterator __f, const_iterator __l, size_type __n,
+                const hasher& __hf, const key_equal& __eql,
+                const allocator_type& __a = allocator_type())
+    : _M_ht(__n, __hf, __eql, __a)
+    { _M_ht.insert_equal(__f, __l); }
+#endif
+
+public:
+  size_type size() const { return _M_ht.size(); }
+  size_type max_size() const { return _M_ht.max_size(); }
+  bool empty() const { return _M_ht.empty(); }
+  void swap(hash_multiset& hs) { _M_ht.swap(hs._M_ht); }
+
+#if @KWSYS_NAMESPACE@_CXX_HAS_MEMBER_TEMPLATES
+  template <class _Val, class _HF, class _EqK, class _Al>
+  friend bool operator== (const hash_multiset<_Val, _HF, _EqK, _Al>&,
+                          const hash_multiset<_Val, _HF, _EqK, _Al>&);
+#else
+  friend bool operator==@KWSYS_NAMESPACE@_CXX_NULL_TEMPLATE_ARGS(const hash_multiset&,
+                                                                 const hash_multiset&);
+#endif
+
+  iterator begin() const { return _M_ht.begin(); }
+  iterator end() const { return _M_ht.end(); }
+
+public:
+  iterator insert(const value_type& __obj)
+    { return _M_ht.insert_equal(__obj); }
+#if @KWSYS_NAMESPACE@_CXX_HAS_MEMBER_TEMPLATES
+  template <class _InputIterator>
+  void insert(_InputIterator __f, _InputIterator __l)
+    { _M_ht.insert_equal(__f,__l); }
+#else
+  void insert(const value_type* __f, const value_type* __l) {
+    _M_ht.insert_equal(__f,__l);
+  }
+  void insert(const_iterator __f, const_iterator __l)
+    { _M_ht.insert_equal(__f, __l); }
+#endif
+  iterator insert_noresize(const value_type& __obj)
+    { return _M_ht.insert_equal_noresize(__obj); }
+
+  iterator find(const key_type& __key) const { return _M_ht.find(__key); }
+
+  size_type count(const key_type& __key) const { return _M_ht.count(__key); }
+
+  kwsys_stl::pair<iterator, iterator> equal_range(const key_type& __key) const
+    { return _M_ht.equal_range(__key); }
+
+  size_type erase(const key_type& __key) {return _M_ht.erase(__key); }
+  void erase(iterator __it) { _M_ht.erase(__it); }
+  void erase(iterator __f, iterator __l) { _M_ht.erase(__f, __l); }
+  void clear() { _M_ht.clear(); }
+
+public:
+  void resize(size_type __hint) { _M_ht.resize(__hint); }
+  size_type bucket_count() const { return _M_ht.bucket_count(); }
+  size_type max_bucket_count() const { return _M_ht.max_bucket_count(); }
+  size_type elems_in_bucket(size_type __n) const
+    { return _M_ht.elems_in_bucket(__n); }
+};
+
+template <class _Val, class _HashFcn, class _EqualKey, class _Alloc>
+inline bool
+operator==(const hash_multiset<_Val,_HashFcn,_EqualKey,_Alloc>& __hs1,
+           const hash_multiset<_Val,_HashFcn,_EqualKey,_Alloc>& __hs2)
+{
+  return __hs1._M_ht == __hs2._M_ht;
+}
+
+template <class _Val, class _HashFcn, class _EqualKey, class _Alloc>
+inline bool
+operator!=(const hash_multiset<_Val,_HashFcn,_EqualKey,_Alloc>& __hs1,
+           const hash_multiset<_Val,_HashFcn,_EqualKey,_Alloc>& __hs2) {
+  return !(__hs1 == __hs2);
+}
+
+template <class _Val, class _HashFcn, class _EqualKey, class _Alloc>
+inline void
+swap(hash_multiset<_Val,_HashFcn,_EqualKey,_Alloc>& __hs1,
+     hash_multiset<_Val,_HashFcn,_EqualKey,_Alloc>& __hs2) {
+  __hs1.swap(__hs2);
+}
+
+} // namespace @KWSYS_NAMESPACE@
+
+#if defined(__sgi) && !defined(__GNUC__) && (_MIPS_SIM != _MIPS_SIM_ABI32)
+# pragma reset woff 1174
+# pragma reset woff 1375
+#endif
+
+#if defined(_MSC_VER)
+# pragma warning (pop)
+#endif
+
+#endif
diff --git a/hashtable.hxx.in b/hashtable.hxx.in
new file mode 100644
index 00000000..d1a15161
--- /dev/null
+++ b/hashtable.hxx.in
@@ -0,0 +1,1088 @@
+/*=========================================================================
+
+  Program:   KWSys - Kitware System Library
+  Module:    hashtable.hxx.in
+
+  Copyright (c) Kitware, Inc., Insight Consortium.  All rights reserved.
+  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
+
+     This software is distributed WITHOUT ANY WARRANTY; without even
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+     PURPOSE.  See the above copyright notices for more information.
+
+=========================================================================*/
+/*
+ * Copyright (c) 1996
+ * Silicon Graphics Computer Systems, Inc.
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.  Silicon Graphics makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ *
+ *
+ * Copyright (c) 1994
+ * Hewlett-Packard Company
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.  Hewlett-Packard Company makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ *
+ */
+#ifndef @KWSYS_NAMESPACE@_hashtable_hxx
+#define @KWSYS_NAMESPACE@_hashtable_hxx
+
+#include <@KWSYS_NAMESPACE@/Configure.hxx>
+
+#include <@KWSYS_NAMESPACE@/stl/algorithm>  // lower_bound
+#include <@KWSYS_NAMESPACE@/stl/functional> // unary_function
+#include <@KWSYS_NAMESPACE@/stl/iterator>   // iterator_traits
+#include <@KWSYS_NAMESPACE@/stl/memory>     // allocator
+#include <@KWSYS_NAMESPACE@/stl/utility>    // pair
+#include <@KWSYS_NAMESPACE@/stl/vector>     // vector
+
+#if defined(_MSC_VER)
+# pragma warning (push)
+# pragma warning (disable:4284)
+# pragma warning (disable:4786)
+#endif
+
+namespace @KWSYS_NAMESPACE@
+{
+
+//----------------------------------------------------------------------------
+// Define an allocator adaptor for platforms that do not provide an
+// allocator with the rebind member.
+#if !@KWSYS_NAMESPACE@_STL_HAS_ALLOCATOR_REBIND
+class hash_allocator_base {};
+bool operator==(const hash_allocator_base&,
+                const hash_allocator_base&) throw() { return true; }
+bool operator!=(const hash_allocator_base&,
+                const hash_allocator_base&) throw() { return false; }
+template <class T, class Alloc>
+class hash_allocator: public hash_allocator_base
+{
+private:
+  // Store the real allocator privately.
+  typedef Alloc alloc_type;
+  typedef typename alloc_type::value_type alloc_value_type;
+  typedef typename alloc_type::pointer alloc_pointer;
+  alloc_type alloc_;
+
+public:
+  // Standard allocator interface.
+  typedef typename alloc_type::size_type size_type;
+  typedef typename alloc_type::difference_type difference_type;
+  typedef T* pointer;
+  typedef const T* const_pointer;
+  typedef T& reference;
+  typedef const T& const_reference;
+  typedef T value_type;
+
+  hash_allocator() throw(): alloc_() {}
+  hash_allocator(const hash_allocator_base& a) throw() : alloc_() {}
+  hash_allocator(const hash_allocator& a) throw() : alloc_(a.alloc_) {}
+  hash_allocator(const alloc_type& a) throw() : alloc_(a) {}
+  ~hash_allocator() throw() {}
+# if @KWSYS_NAMESPACE@_CXX_HAS_MEMBER_TEMPLATES
+  template <class U>
+  struct rebind { typedef hash_allocator<U, alloc_type> other; };
+# endif
+  pointer address(reference x) const { return &x; }
+  const_pointer address(const_reference x) const { return &x; }
+  pointer allocate(size_type n=1, kwsys_stl::allocator<void>::const_pointer hint = 0)
+    {
+    if(n)
+      {
+      return static_cast<pointer>(static_cast<void*>(alloc_.allocate(n*chunk(), hint)));
+      }
+    else
+      {
+      return 0;
+      }
+    }
+  void deallocate(pointer p, size_type n=1)
+    {
+    if(n)
+      {
+      alloc_.deallocate(static_cast<alloc_pointer>(static_cast<void*>(p)), n*chunk());
+      }
+    }
+  size_type max_size() const throw()
+    {
+    size_type n = alloc_.max_size() / chunk();
+    return n>0? n:1;
+    }
+  void construct(pointer p, const value_type& val) { new (p) value_type(val); }
+  void destroy(pointer p) { (void)p; p->~value_type(); }
+private:
+  // Returns the number of the real allocator's allocation units
+  // needed to allocate one unit for this allocator.
+  static size_type chunk()
+    { return (sizeof(value_type)/sizeof(alloc_value_type)+
+              (sizeof(value_type)%sizeof(alloc_value_type)>0)); }
+};
+#endif
+
+template <class _Val>
+struct _Hashtable_node
+{
+  _Hashtable_node* _M_next;
+  _Val _M_val;
+};
+
+template <class _Val, class _Key, class _HashFcn,
+          class _ExtractKey, class _EqualKey,
+          class _Alloc = kwsys_stl::allocator<char> >
+class hashtable;
+
+template <class _Val, class _Key, class _HashFcn,
+          class _ExtractKey, class _EqualKey, class _Alloc>
+struct _Hashtable_iterator;
+
+template <class _Val, class _Key, class _HashFcn,
+          class _ExtractKey, class _EqualKey, class _Alloc>
+struct _Hashtable_const_iterator;
+
+template <class _Val, class _Key, class _HashFcn,
+          class _ExtractKey, class _EqualKey, class _Alloc>
+struct _Hashtable_iterator {
+  typedef hashtable<_Val,_Key,_HashFcn,_ExtractKey,_EqualKey,_Alloc>
+          _Hashtable;
+  typedef _Hashtable_iterator<_Val, _Key, _HashFcn,
+                              _ExtractKey, _EqualKey, _Alloc>
+          iterator;
+  typedef _Hashtable_const_iterator<_Val, _Key, _HashFcn,
+                                    _ExtractKey, _EqualKey, _Alloc>
+          const_iterator;
+  typedef _Hashtable_node<_Val> _Node;
+
+  typedef kwsys_stl::forward_iterator_tag iterator_category;
+  typedef _Val value_type;
+  typedef ptrdiff_t difference_type;
+  typedef size_t size_type;
+  typedef _Val& reference;
+  typedef _Val* pointer;
+
+  _Node* _M_cur;
+  _Hashtable* _M_ht;
+
+  _Hashtable_iterator(_Node* __n, _Hashtable* __tab)
+    : _M_cur(__n), _M_ht(__tab) {}
+  _Hashtable_iterator() {}
+  reference operator*() const { return _M_cur->_M_val; }
+  pointer operator->() const { return &(operator*()); }
+  iterator& operator++();
+  iterator operator++(int);
+  bool operator==(const iterator& __it) const
+    { return _M_cur == __it._M_cur; }
+  bool operator!=(const iterator& __it) const
+    { return _M_cur != __it._M_cur; }
+};
+
+
+template <class _Val, class _Key, class _HashFcn,
+          class _ExtractKey, class _EqualKey, class _Alloc>
+struct _Hashtable_const_iterator {
+  typedef hashtable<_Val,_Key,_HashFcn,_ExtractKey,_EqualKey,_Alloc>
+          _Hashtable;
+  typedef _Hashtable_iterator<_Val,_Key,_HashFcn,
+                              _ExtractKey,_EqualKey,_Alloc>
+          iterator;
+  typedef _Hashtable_const_iterator<_Val, _Key, _HashFcn,
+                                    _ExtractKey, _EqualKey, _Alloc>
+          const_iterator;
+  typedef _Hashtable_node<_Val> _Node;
+
+  typedef kwsys_stl::forward_iterator_tag iterator_category;
+  typedef _Val value_type;
+  typedef ptrdiff_t difference_type;
+  typedef size_t size_type;
+  typedef const _Val& reference;
+  typedef const _Val* pointer;
+
+  const _Node* _M_cur;
+  const _Hashtable* _M_ht;
+
+  _Hashtable_const_iterator(const _Node* __n, const _Hashtable* __tab)
+    : _M_cur(__n), _M_ht(__tab) {}
+  _Hashtable_const_iterator() {}
+  _Hashtable_const_iterator(const iterator& __it)
+    : _M_cur(__it._M_cur), _M_ht(__it._M_ht) {}
+  reference operator*() const { return _M_cur->_M_val; }
+  pointer operator->() const { return &(operator*()); }
+  const_iterator& operator++();
+  const_iterator operator++(int);
+  bool operator==(const const_iterator& __it) const
+    { return _M_cur == __it._M_cur; }
+  bool operator!=(const const_iterator& __it) const
+    { return _M_cur != __it._M_cur; }
+};
+
+// Note: assumes long is at least 32 bits.
+enum { _stl_num_primes = 28 };
+
+static const unsigned long _stl_prime_list[_stl_num_primes] =
+{
+  53ul,         97ul,         193ul,       389ul,       769ul,
+  1543ul,       3079ul,       6151ul,      12289ul,     24593ul,
+  49157ul,      98317ul,      196613ul,    393241ul,    786433ul,
+  1572869ul,    3145739ul,    6291469ul,   12582917ul,  25165843ul,
+  50331653ul,   100663319ul,  201326611ul, 402653189ul, 805306457ul,
+  1610612741ul, 3221225473ul, 4294967291ul
+};
+
+inline unsigned long _stl_next_prime(unsigned long __n)
+{
+  const unsigned long* __first = _stl_prime_list;
+  const unsigned long* __last = _stl_prime_list + (int)_stl_num_primes;
+  const unsigned long* pos = kwsys_stl::lower_bound(__first, __last, __n);
+  return pos == __last ? *(__last - 1) : *pos;
+}
+
+// Forward declaration of operator==.
+
+template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
+class hashtable;
+
+template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
+bool operator==(const hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>& __ht1,
+                const hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>& __ht2);
+
+// Hashtables handle allocators a bit differently than other containers
+//  do.  If we're using standard-conforming allocators, then a hashtable
+//  unconditionally has a member variable to hold its allocator, even if
+//  it so happens that all instances of the allocator type are identical.
+// This is because, for hashtables, this extra storage is negligible.
+//  Additionally, a base class wouldn't serve any other purposes; it
+//  wouldn't, for example, simplify the exception-handling code.
+
+template <class _Val, class _Key, class _HashFcn,
+          class _ExtractKey, class _EqualKey, class _Alloc>
+class hashtable {
+public:
+  typedef _Key key_type;
+  typedef _Val value_type;
+  typedef _HashFcn hasher;
+  typedef _EqualKey key_equal;
+
+  typedef size_t            size_type;
+  typedef ptrdiff_t         difference_type;
+  typedef value_type*       pointer;
+  typedef const value_type* const_pointer;
+  typedef value_type&       reference;
+  typedef const value_type& const_reference;
+
+  hasher hash_funct() const { return _M_hash; }
+  key_equal key_eq() const { return _M_equals; }
+
+private:
+  typedef _Hashtable_node<_Val> _Node;
+
+#if @KWSYS_NAMESPACE@_STL_HAS_ALLOCATOR_REBIND
+public:
+  typedef typename _Alloc::template rebind<_Val>::other allocator_type;
+  allocator_type get_allocator() const { return _M_node_allocator; }
+private:
+  typedef typename _Alloc::template rebind<_Node>::other _M_node_allocator_type;
+  typedef kwsys_stl::vector<_Node*,_Alloc> _M_buckets_type;
+#else
+public:
+  typedef hash_allocator<_Val, _Alloc> allocator_type;
+  allocator_type get_allocator() const { return allocator_type(); }
+private:
+  typedef hash_allocator<_Node, _Alloc> _M_node_allocator_type;
+  typedef hash_allocator<_Node*, _Alloc> _M_node_ptr_allocator_type;
+  typedef kwsys_stl::vector<_Node*,_M_node_ptr_allocator_type> _M_buckets_type;
+#endif
+
+private:
+  _M_node_allocator_type _M_node_allocator;
+  hasher                 _M_hash;
+  key_equal              _M_equals;
+  _ExtractKey            _M_get_key;
+  _M_buckets_type        _M_buckets;
+  size_type              _M_num_elements;
+
+  _Node* _M_get_node() { return _M_node_allocator.allocate(1); }
+  void _M_put_node(_Node* __p) { _M_node_allocator.deallocate(__p, 1); }
+
+public:
+  typedef _Hashtable_iterator<_Val,_Key,_HashFcn,_ExtractKey,_EqualKey,_Alloc>
+          iterator;
+  typedef _Hashtable_const_iterator<_Val,_Key,_HashFcn,_ExtractKey,_EqualKey,
+                                    _Alloc>
+          const_iterator;
+
+  friend struct
+  _Hashtable_iterator<_Val,_Key,_HashFcn,_ExtractKey,_EqualKey,_Alloc>;
+  friend struct
+  _Hashtable_const_iterator<_Val,_Key,_HashFcn,_ExtractKey,_EqualKey,_Alloc>;
+
+public:
+  hashtable(size_type __n,
+            const _HashFcn&    __hf,
+            const _EqualKey&   __eql,
+            const _ExtractKey& __ext,
+            const allocator_type& __a = allocator_type())
+    : _M_node_allocator(__a),
+      _M_hash(__hf),
+      _M_equals(__eql),
+      _M_get_key(__ext),
+      _M_buckets(__a),
+      _M_num_elements(0)
+  {
+    _M_initialize_buckets(__n);
+  }
+
+  hashtable(size_type __n,
+            const _HashFcn&    __hf,
+            const _EqualKey&   __eql,
+            const allocator_type& __a = allocator_type())
+    : _M_node_allocator(__a),
+      _M_hash(__hf),
+      _M_equals(__eql),
+      _M_get_key(_ExtractKey()),
+      _M_buckets(__a),
+      _M_num_elements(0)
+  {
+    _M_initialize_buckets(__n);
+  }
+
+  hashtable(const hashtable& __ht)
+    : _M_node_allocator(__ht.get_allocator()),
+      _M_hash(__ht._M_hash),
+      _M_equals(__ht._M_equals),
+      _M_get_key(__ht._M_get_key),
+      _M_buckets(__ht.get_allocator()),
+      _M_num_elements(0)
+  {
+    _M_copy_from(__ht);
+  }
+
+  hashtable& operator= (const hashtable& __ht)
+  {
+    if (&__ht != this) {
+      clear();
+      _M_hash = __ht._M_hash;
+      _M_equals = __ht._M_equals;
+      _M_get_key = __ht._M_get_key;
+      _M_copy_from(__ht);
+    }
+    return *this;
+  }
+
+  ~hashtable() { clear(); }
+
+  size_type size() const { return _M_num_elements; }
+  size_type max_size() const { return size_type(-1); }
+  bool empty() const { return size() == 0; }
+
+  void swap(hashtable& __ht)
+  {
+    kwsys_stl::swap(_M_hash, __ht._M_hash);
+    kwsys_stl::swap(_M_equals, __ht._M_equals);
+    kwsys_stl::swap(_M_get_key, __ht._M_get_key);
+    _M_buckets.swap(__ht._M_buckets);
+    kwsys_stl::swap(_M_num_elements, __ht._M_num_elements);
+  }
+
+  iterator begin()
+  {
+    for (size_type __n = 0; __n < _M_buckets.size(); ++__n)
+      if (_M_buckets[__n])
+        return iterator(_M_buckets[__n], this);
+    return end();
+  }
+
+  iterator end() { return iterator(0, this); }
+
+  const_iterator begin() const
+  {
+    for (size_type __n = 0; __n < _M_buckets.size(); ++__n)
+      if (_M_buckets[__n])
+        return const_iterator(_M_buckets[__n], this);
+    return end();
+  }
+
+  const_iterator end() const { return const_iterator(0, this); }
+
+#if @KWSYS_NAMESPACE@_CXX_HAS_MEMBER_TEMPLATES
+  template <class _Vl, class _Ky, class _HF, class _Ex, class _Eq, class _Al>
+  friend bool operator== (const hashtable<_Vl, _Ky, _HF, _Ex, _Eq, _Al>&,
+                          const hashtable<_Vl, _Ky, _HF, _Ex, _Eq, _Al>&);
+#else
+  friend bool operator==@KWSYS_NAMESPACE@_CXX_NULL_TEMPLATE_ARGS(const hashtable&,
+                                                                 const hashtable&);
+#endif
+
+public:
+
+  size_type bucket_count() const { return _M_buckets.size(); }
+
+  size_type max_bucket_count() const
+    { return _stl_prime_list[(int)_stl_num_primes - 1]; }
+
+  size_type elems_in_bucket(size_type __bucket) const
+  {
+    size_type __result = 0;
+    for (_Node* __cur = _M_buckets[__bucket]; __cur; __cur = __cur->_M_next)
+      __result += 1;
+    return __result;
+  }
+
+  kwsys_stl::pair<iterator, bool> insert_unique(const value_type& __obj)
+  {
+    resize(_M_num_elements + 1);
+    return insert_unique_noresize(__obj);
+  }
+
+  iterator insert_equal(const value_type& __obj)
+  {
+    resize(_M_num_elements + 1);
+    return insert_equal_noresize(__obj);
+  }
+
+  kwsys_stl::pair<iterator, bool> insert_unique_noresize(const value_type& __obj);
+  iterator insert_equal_noresize(const value_type& __obj);
+
+#if @KWSYS_NAMESPACE@_CXX_HAS_MEMBER_TEMPLATES
+  template <class _InputIterator>
+  void insert_unique(_InputIterator __f, _InputIterator __l)
+  {
+    typedef typename kwsys_stl::iterator_traits<_InputIterator>::iterator_category
+      iterator_category;
+    insert_unique(__f, __l, iterator_category());
+  }
+
+  template <class _InputIterator>
+  void insert_equal(_InputIterator __f, _InputIterator __l)
+  {
+    typedef typename kwsys_stl::iterator_traits<_InputIterator>::iterator_category
+      iterator_category;
+    insert_equal(__f, __l, iterator_category());
+  }
+
+  template <class _InputIterator>
+  void insert_unique(_InputIterator __f, _InputIterator __l,
+                     kwsys_stl::input_iterator_tag)
+  {
+    for ( ; __f != __l; ++__f)
+      insert_unique(*__f);
+  }
+
+  template <class _InputIterator>
+  void insert_equal(_InputIterator __f, _InputIterator __l,
+                    kwsys_stl::input_iterator_tag)
+  {
+    for ( ; __f != __l; ++__f)
+      insert_equal(*__f);
+  }
+
+  template <class _ForwardIterator>
+  void insert_unique(_ForwardIterator __f, _ForwardIterator __l,
+                     kwsys_stl::forward_iterator_tag)
+  {
+    size_type __n = 0;
+    kwsys_stl::distance(__f, __l, __n);
+    resize(_M_num_elements + __n);
+    for ( ; __n > 0; --__n, ++__f)
+      insert_unique_noresize(*__f);
+  }
+
+  template <class _ForwardIterator>
+  void insert_equal(_ForwardIterator __f, _ForwardIterator __l,
+                    kwsys_stl::forward_iterator_tag)
+  {
+    size_type __n = 0;
+    kwsys_stl::distance(__f, __l, __n);
+    resize(_M_num_elements + __n);
+    for ( ; __n > 0; --__n, ++__f)
+      insert_equal_noresize(*__f);
+  }
+
+#else
+  void insert_unique(const value_type* __f, const value_type* __l)
+  {
+    size_type __n = __l - __f;
+    resize(_M_num_elements + __n);
+    for ( ; __n > 0; --__n, ++__f)
+      insert_unique_noresize(*__f);
+  }
+
+  void insert_equal(const value_type* __f, const value_type* __l)
+  {
+    size_type __n = __l - __f;
+    resize(_M_num_elements + __n);
+    for ( ; __n > 0; --__n, ++__f)
+      insert_equal_noresize(*__f);
+  }
+
+  void insert_unique(const_iterator __f, const_iterator __l)
+  {
+    size_type __n = 0;
+    kwsys_stl::distance(__f, __l, __n);
+    resize(_M_num_elements + __n);
+    for ( ; __n > 0; --__n, ++__f)
+      insert_unique_noresize(*__f);
+  }
+
+  void insert_equal(const_iterator __f, const_iterator __l)
+  {
+    size_type __n = 0;
+    kwsys_stl::distance(__f, __l, __n);
+    resize(_M_num_elements + __n);
+    for ( ; __n > 0; --__n, ++__f)
+      insert_equal_noresize(*__f);
+  }
+#endif
+
+  reference find_or_insert(const value_type& __obj);
+
+  iterator find(const key_type& __key)
+  {
+    size_type __n = _M_bkt_num_key(__key);
+    _Node* __first;
+    for ( __first = _M_buckets[__n];
+          __first && !_M_equals(_M_get_key(__first->_M_val), __key);
+          __first = __first->_M_next)
+      {}
+    return iterator(__first, this);
+  }
+
+  const_iterator find(const key_type& __key) const
+  {
+    size_type __n = _M_bkt_num_key(__key);
+    const _Node* __first;
+    for ( __first = _M_buckets[__n];
+          __first && !_M_equals(_M_get_key(__first->_M_val), __key);
+          __first = __first->_M_next)
+      {}
+    return const_iterator(__first, this);
+  }
+
+  size_type count(const key_type& __key) const
+  {
+    const size_type __n = _M_bkt_num_key(__key);
+    size_type __result = 0;
+
+    for (const _Node* __cur = _M_buckets[__n]; __cur; __cur = __cur->_M_next)
+      if (_M_equals(_M_get_key(__cur->_M_val), __key))
+        ++__result;
+    return __result;
+  }
+
+  kwsys_stl::pair<iterator, iterator>
+  equal_range(const key_type& __key);
+
+  kwsys_stl::pair<const_iterator, const_iterator>
+  equal_range(const key_type& __key) const;
+
+  size_type erase(const key_type& __key);
+  void erase(const iterator& __it);
+  void erase(iterator __first, iterator __last);
+
+  void erase(const const_iterator& __it);
+  void erase(const_iterator __first, const_iterator __last);
+
+  void resize(size_type __num_elements_hint);
+  void clear();
+
+private:
+  size_type _M_next_size(size_type __n) const
+    { return _stl_next_prime(__n); }
+
+  void _M_initialize_buckets(size_type __n)
+  {
+    const size_type __n_buckets = _M_next_size(__n);
+    _M_buckets.reserve(__n_buckets);
+    _M_buckets.insert(_M_buckets.end(), __n_buckets, (_Node*) 0);
+    _M_num_elements = 0;
+  }
+
+  size_type _M_bkt_num_key(const key_type& __key) const
+  {
+    return _M_bkt_num_key(__key, _M_buckets.size());
+  }
+
+  size_type _M_bkt_num(const value_type& __obj) const
+  {
+    return _M_bkt_num_key(_M_get_key(__obj));
+  }
+
+  size_type _M_bkt_num_key(const key_type& __key, size_t __n) const
+  {
+    return _M_hash(__key) % __n;
+  }
+
+  size_type _M_bkt_num(const value_type& __obj, size_t __n) const
+  {
+    return _M_bkt_num_key(_M_get_key(__obj), __n);
+  }
+
+  void construct(_Val* p, const _Val& v)
+    {
+    new (p) _Val(v);
+    }
+  void destroy(_Val* p)
+    {
+    (void)p;
+    p->~_Val();
+    }
+
+  _Node* _M_new_node(const value_type& __obj)
+  {
+    _Node* __n = _M_get_node();
+    __n->_M_next = 0;
+    try {
+      construct(&__n->_M_val, __obj);
+      return __n;
+    }
+    catch(...) {_M_put_node(__n); throw;}
+  }
+
+  void _M_delete_node(_Node* __n)
+  {
+    destroy(&__n->_M_val);
+    _M_put_node(__n);
+  }
+
+  void _M_erase_bucket(const size_type __n, _Node* __first, _Node* __last);
+  void _M_erase_bucket(const size_type __n, _Node* __last);
+
+  void _M_copy_from(const hashtable& __ht);
+
+};
+
+template <class _Val, class _Key, class _HF, class _ExK, class _EqK,
+          class _All>
+_Hashtable_iterator<_Val,_Key,_HF,_ExK,_EqK,_All>&
+_Hashtable_iterator<_Val,_Key,_HF,_ExK,_EqK,_All>::operator++()
+{
+  const _Node* __old = _M_cur;
+  _M_cur = _M_cur->_M_next;
+  if (!_M_cur) {
+    size_type __bucket = _M_ht->_M_bkt_num(__old->_M_val);
+    while (!_M_cur && ++__bucket < _M_ht->_M_buckets.size())
+      _M_cur = _M_ht->_M_buckets[__bucket];
+  }
+  return *this;
+}
+
+template <class _Val, class _Key, class _HF, class _ExK, class _EqK,
+          class _All>
+inline _Hashtable_iterator<_Val,_Key,_HF,_ExK,_EqK,_All>
+_Hashtable_iterator<_Val,_Key,_HF,_ExK,_EqK,_All>::operator++(int)
+{
+  iterator __tmp = *this;
+  ++*this;
+  return __tmp;
+}
+
+template <class _Val, class _Key, class _HF, class _ExK, class _EqK,
+          class _All>
+_Hashtable_const_iterator<_Val,_Key,_HF,_ExK,_EqK,_All>&
+_Hashtable_const_iterator<_Val,_Key,_HF,_ExK,_EqK,_All>::operator++()
+{
+  const _Node* __old = _M_cur;
+  _M_cur = _M_cur->_M_next;
+  if (!_M_cur) {
+    size_type __bucket = _M_ht->_M_bkt_num(__old->_M_val);
+    while (!_M_cur && ++__bucket < _M_ht->_M_buckets.size())
+      _M_cur = _M_ht->_M_buckets[__bucket];
+  }
+  return *this;
+}
+
+template <class _Val, class _Key, class _HF, class _ExK, class _EqK,
+          class _All>
+inline _Hashtable_const_iterator<_Val,_Key,_HF,_ExK,_EqK,_All>
+_Hashtable_const_iterator<_Val,_Key,_HF,_ExK,_EqK,_All>::operator++(int)
+{
+  const_iterator __tmp = *this;
+  ++*this;
+  return __tmp;
+}
+
+template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
+bool operator==(const hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>& __ht1,
+                const hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>& __ht2)
+{
+  typedef typename hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::_Node _Node;
+  if (__ht1._M_buckets.size() != __ht2._M_buckets.size())
+    return false;
+  for (int __n = 0; __n < __ht1._M_buckets.size(); ++__n) {
+    _Node* __cur1 = __ht1._M_buckets[__n];
+    _Node* __cur2 = __ht2._M_buckets[__n];
+    for ( ; __cur1 && __cur2 && __cur1->_M_val == __cur2->_M_val;
+          __cur1 = __cur1->_M_next, __cur2 = __cur2->_M_next)
+      {}
+    if (__cur1 || __cur2)
+      return false;
+  }
+  return true;
+}
+
+template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
+inline bool operator!=(const hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>& __ht1,
+                       const hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>& __ht2) {
+  return !(__ht1 == __ht2);
+}
+
+template <class _Val, class _Key, class _HF, class _Extract, class _EqKey,
+          class _All>
+inline void swap(hashtable<_Val, _Key, _HF, _Extract, _EqKey, _All>& __ht1,
+                 hashtable<_Val, _Key, _HF, _Extract, _EqKey, _All>& __ht2) {
+  __ht1.swap(__ht2);
+}
+
+template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
+kwsys_stl::pair<@KWSYS_NAMESPACE@_CXX_DECL_TYPENAME hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::iterator, bool>
+hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>
+  ::insert_unique_noresize(const value_type& __obj)
+{
+  const size_type __n = _M_bkt_num(__obj);
+  _Node* __first = _M_buckets[__n];
+
+  for (_Node* __cur = __first; __cur; __cur = __cur->_M_next)
+    if (_M_equals(_M_get_key(__cur->_M_val), _M_get_key(__obj)))
+      return kwsys_stl::pair<iterator, bool>(iterator(__cur, this), false);
+
+  _Node* __tmp = _M_new_node(__obj);
+  __tmp->_M_next = __first;
+  _M_buckets[__n] = __tmp;
+  ++_M_num_elements;
+  return kwsys_stl::pair<iterator, bool>(iterator(__tmp, this), true);
+}
+
+template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
+typename hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::iterator
+hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>
+  ::insert_equal_noresize(const value_type& __obj)
+{
+  const size_type __n = _M_bkt_num(__obj);
+  _Node* __first = _M_buckets[__n];
+
+  for (_Node* __cur = __first; __cur; __cur = __cur->_M_next)
+    if (_M_equals(_M_get_key(__cur->_M_val), _M_get_key(__obj))) {
+      _Node* __tmp = _M_new_node(__obj);
+      __tmp->_M_next = __cur->_M_next;
+      __cur->_M_next = __tmp;
+      ++_M_num_elements;
+      return iterator(__tmp, this);
+    }
+
+  _Node* __tmp = _M_new_node(__obj);
+  __tmp->_M_next = __first;
+  _M_buckets[__n] = __tmp;
+  ++_M_num_elements;
+  return iterator(__tmp, this);
+}
+
+template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
+typename hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::reference
+hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::find_or_insert(const value_type& __obj)
+{
+  resize(_M_num_elements + 1);
+
+  size_type __n = _M_bkt_num(__obj);
+  _Node* __first = _M_buckets[__n];
+
+  for (_Node* __cur = __first; __cur; __cur = __cur->_M_next)
+    if (_M_equals(_M_get_key(__cur->_M_val), _M_get_key(__obj)))
+      return __cur->_M_val;
+
+  _Node* __tmp = _M_new_node(__obj);
+  __tmp->_M_next = __first;
+  _M_buckets[__n] = __tmp;
+  ++_M_num_elements;
+  return __tmp->_M_val;
+}
+
+template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
+kwsys_stl::pair<@KWSYS_NAMESPACE@_CXX_DECL_TYPENAME hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::iterator,
+     @KWSYS_NAMESPACE@_CXX_DECL_TYPENAME hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::iterator>
+hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::equal_range(const key_type& __key)
+{
+  typedef kwsys_stl::pair<iterator, iterator> _Pii;
+  const size_type __n = _M_bkt_num_key(__key);
+
+  for (_Node* __first = _M_buckets[__n]; __first; __first = __first->_M_next)
+    if (_M_equals(_M_get_key(__first->_M_val), __key)) {
+      for (_Node* __cur = __first->_M_next; __cur; __cur = __cur->_M_next)
+        if (!_M_equals(_M_get_key(__cur->_M_val), __key))
+          return _Pii(iterator(__first, this), iterator(__cur, this));
+      for (size_type __m = __n + 1; __m < _M_buckets.size(); ++__m)
+        if (_M_buckets[__m])
+          return _Pii(iterator(__first, this),
+                     iterator(_M_buckets[__m], this));
+      return _Pii(iterator(__first, this), end());
+    }
+  return _Pii(end(), end());
+}
+
+template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
+kwsys_stl::pair<@KWSYS_NAMESPACE@_CXX_DECL_TYPENAME hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::const_iterator,
+     @KWSYS_NAMESPACE@_CXX_DECL_TYPENAME hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::const_iterator>
+hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>
+  ::equal_range(const key_type& __key) const
+{
+  typedef kwsys_stl::pair<const_iterator, const_iterator> _Pii;
+  const size_type __n = _M_bkt_num_key(__key);
+
+  for (const _Node* __first = _M_buckets[__n] ;
+       __first;
+       __first = __first->_M_next) {
+    if (_M_equals(_M_get_key(__first->_M_val), __key)) {
+      for (const _Node* __cur = __first->_M_next;
+           __cur;
+           __cur = __cur->_M_next)
+        if (!_M_equals(_M_get_key(__cur->_M_val), __key))
+          return _Pii(const_iterator(__first, this),
+                      const_iterator(__cur, this));
+      for (size_type __m = __n + 1; __m < _M_buckets.size(); ++__m)
+        if (_M_buckets[__m])
+          return _Pii(const_iterator(__first, this),
+                      const_iterator(_M_buckets[__m], this));
+      return _Pii(const_iterator(__first, this), end());
+    }
+  }
+  return _Pii(end(), end());
+}
+
+template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
+typename hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::size_type
+hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::erase(const key_type& __key)
+{
+  const size_type __n = _M_bkt_num_key(__key);
+  _Node* __first = _M_buckets[__n];
+  size_type __erased = 0;
+
+  if (__first) {
+    _Node* __cur = __first;
+    _Node* __next = __cur->_M_next;
+    while (__next) {
+      if (_M_equals(_M_get_key(__next->_M_val), __key)) {
+        __cur->_M_next = __next->_M_next;
+        _M_delete_node(__next);
+        __next = __cur->_M_next;
+        ++__erased;
+        --_M_num_elements;
+      }
+      else {
+        __cur = __next;
+        __next = __cur->_M_next;
+      }
+    }
+    if (_M_equals(_M_get_key(__first->_M_val), __key)) {
+      _M_buckets[__n] = __first->_M_next;
+      _M_delete_node(__first);
+      ++__erased;
+      --_M_num_elements;
+    }
+  }
+  return __erased;
+}
+
+template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
+void hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::erase(const iterator& __it)
+{
+  _Node* __p = __it._M_cur;
+  if (__p) {
+    const size_type __n = _M_bkt_num(__p->_M_val);
+    _Node* __cur = _M_buckets[__n];
+
+    if (__cur == __p) {
+      _M_buckets[__n] = __cur->_M_next;
+      _M_delete_node(__cur);
+      --_M_num_elements;
+    }
+    else {
+      _Node* __next = __cur->_M_next;
+      while (__next) {
+        if (__next == __p) {
+          __cur->_M_next = __next->_M_next;
+          _M_delete_node(__next);
+          --_M_num_elements;
+          break;
+        }
+        else {
+          __cur = __next;
+          __next = __cur->_M_next;
+        }
+      }
+    }
+  }
+}
+
+template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
+void hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>
+  ::erase(iterator __first, iterator __last)
+{
+  size_type __f_bucket = __first._M_cur ?
+    _M_bkt_num(__first._M_cur->_M_val) : _M_buckets.size();
+  size_type __l_bucket = __last._M_cur ?
+    _M_bkt_num(__last._M_cur->_M_val) : _M_buckets.size();
+
+  if (__first._M_cur == __last._M_cur)
+    return;
+  else if (__f_bucket == __l_bucket)
+    _M_erase_bucket(__f_bucket, __first._M_cur, __last._M_cur);
+  else {
+    _M_erase_bucket(__f_bucket, __first._M_cur, 0);
+    for (size_type __n = __f_bucket + 1; __n < __l_bucket; ++__n)
+      _M_erase_bucket(__n, 0);
+    if (__l_bucket != _M_buckets.size())
+      _M_erase_bucket(__l_bucket, __last._M_cur);
+  }
+}
+
+template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
+inline void
+hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::erase(const_iterator __first,
+                                             const_iterator __last)
+{
+  erase(iterator(const_cast<_Node*>(__first._M_cur),
+                 const_cast<hashtable*>(__first._M_ht)),
+        iterator(const_cast<_Node*>(__last._M_cur),
+                 const_cast<hashtable*>(__last._M_ht)));
+}
+
+template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
+inline void
+hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::erase(const const_iterator& __it)
+{
+  erase(iterator(const_cast<_Node*>(__it._M_cur),
+                 const_cast<hashtable*>(__it._M_ht)));
+}
+
+template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
+void hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>
+  ::resize(size_type __num_elements_hint)
+{
+  const size_type __old_n = _M_buckets.size();
+  if (__num_elements_hint > __old_n) {
+    const size_type __n = _M_next_size(__num_elements_hint);
+    if (__n > __old_n) {
+      _M_buckets_type __tmp(__n, (_Node*)(0),
+                                 _M_buckets.get_allocator());
+      try {
+        for (size_type __bucket = 0; __bucket < __old_n; ++__bucket) {
+          _Node* __first = _M_buckets[__bucket];
+          while (__first) {
+            size_type __new_bucket = _M_bkt_num(__first->_M_val, __n);
+            _M_buckets[__bucket] = __first->_M_next;
+            __first->_M_next = __tmp[__new_bucket];
+            __tmp[__new_bucket] = __first;
+            __first = _M_buckets[__bucket];
+          }
+        }
+        _M_buckets.swap(__tmp);
+      }
+      catch(...) {
+        for (size_type __bucket = 0; __bucket < __tmp.size(); ++__bucket) {
+          while (__tmp[__bucket]) {
+            _Node* __next = __tmp[__bucket]->_M_next;
+            _M_delete_node(__tmp[__bucket]);
+            __tmp[__bucket] = __next;
+          }
+        }
+        throw;
+      }
+    }
+  }
+}
+
+template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
+void hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>
+  ::_M_erase_bucket(const size_type __n, _Node* __first, _Node* __last)
+{
+  _Node* __cur = _M_buckets[__n];
+  if (__cur == __first)
+    _M_erase_bucket(__n, __last);
+  else {
+    _Node* __next;
+    for (__next = __cur->_M_next;
+         __next != __first;
+         __cur = __next, __next = __cur->_M_next)
+      ;
+    while (__next != __last) {
+      __cur->_M_next = __next->_M_next;
+      _M_delete_node(__next);
+      __next = __cur->_M_next;
+      --_M_num_elements;
+    }
+  }
+}
+
+template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
+void hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>
+  ::_M_erase_bucket(const size_type __n, _Node* __last)
+{
+  _Node* __cur = _M_buckets[__n];
+  while (__cur != __last) {
+    _Node* __next = __cur->_M_next;
+    _M_delete_node(__cur);
+    __cur = __next;
+    _M_buckets[__n] = __cur;
+    --_M_num_elements;
+  }
+}
+
+template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
+void hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::clear()
+{
+  for (size_type __i = 0; __i < _M_buckets.size(); ++__i) {
+    _Node* __cur = _M_buckets[__i];
+    while (__cur != 0) {
+      _Node* __next = __cur->_M_next;
+      _M_delete_node(__cur);
+      __cur = __next;
+    }
+    _M_buckets[__i] = 0;
+  }
+  _M_num_elements = 0;
+}
+
+
+template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
+void hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>
+  ::_M_copy_from(const hashtable& __ht)
+{
+  _M_buckets.clear();
+  _M_buckets.reserve(__ht._M_buckets.size());
+  _M_buckets.insert(_M_buckets.end(), __ht._M_buckets.size(), (_Node*) 0);
+  try {
+    for (size_type __i = 0; __i < __ht._M_buckets.size(); ++__i) {
+      const _Node* __cur = __ht._M_buckets[__i];
+      if (__cur) {
+        _Node* __copy = _M_new_node(__cur->_M_val);
+        _M_buckets[__i] = __copy;
+
+        for (_Node* __next = __cur->_M_next;
+             __next;
+             __cur = __next, __next = __cur->_M_next) {
+          __copy->_M_next = _M_new_node(__next->_M_val);
+          __copy = __copy->_M_next;
+        }
+      }
+    }
+    _M_num_elements = __ht._M_num_elements;
+  }
+  catch(...) {clear(); throw;}
+}
+
+} // namespace @KWSYS_NAMESPACE@
+
+#if defined(_MSC_VER)
+# pragma warning (pop)
+#endif
+
+#endif
diff --git a/kwsysPlatformCxxTests.cxx b/kwsysPlatformCxxTests.cxx
index 5d247661..c1feca1d 100644
--- a/kwsysPlatformCxxTests.cxx
+++ b/kwsysPlatformCxxTests.cxx
@@ -1,3 +1,12 @@
+// Setup for tests that use result of stl namespace test.
+#if defined(KWSYS_STL_HAVE_STD)
+# if KWSYS_STL_HAVE_STD
+#  define kwsys_stl std
+# else
+#  define kwsys_stl
+# endif
+#endif
+
 #ifdef TEST_KWSYS_STL_HAVE_STD
 #include <list>
 void f(std::list<int>*) {}
@@ -31,11 +40,6 @@ int main() { return 0; }
 #endif
 
 #ifdef TEST_KWSYS_STL_STRING_HAVE_OSTREAM
-# if KWSYS_STL_HAVE_STD
-#  define kwsys_stl std
-# else
-#  define kwsys_stl
-# endif
 # include <iostream.h>
 # include <string>
 void f(ostream& os, const kwsys_stl::string& s) { os << s; }
@@ -43,11 +47,6 @@ int main() { return 0; }
 #endif
 
 #ifdef TEST_KWSYS_STL_STRING_HAVE_ISTREAM
-# if KWSYS_STL_HAVE_STD
-#  define kwsys_stl std
-# else
-#  define kwsys_stl
-# endif
 # include <iostream.h>
 # include <string>
 void f(istream& is, kwsys_stl::string& s) { is >> s; }
@@ -55,16 +54,73 @@ int main() { return 0; }
 #endif
 
 #ifdef TEST_KWSYS_STL_STRING_HAVE_NEQ_CHAR
-# if KWSYS_STL_HAVE_STD
-#  define kwsys_stl std
-# else
-#  define kwsys_stl
-# endif
 # include <string>
 bool f(const kwsys_stl::string& s) { return s != ""; }
 int main() { return 0; }
 #endif
 
+#ifdef TEST_KWSYS_CXX_HAS_NULL_TEMPLATE_ARGS
+template <class T> class A;
+template <class T> int f(A<T>&);
+template <class T> class A
+{
+public:
+  // "friend int f<>(A<T>&)" would conform
+  friend int f(A<T>&);
+private:
+  int x;
+};
+
+template <class T> int f(A<T>& a) { return a.x = 0; }
+template int f(A<int>&);
+
+int main()
+{
+  A<int> a;
+  return f(a);
+}
+#endif
+
+#ifdef TEST_KWSYS_CXX_HAS_MEMBER_TEMPLATES
+template <class U>
+class A
+{
+public:
+  U* ptr;
+  template <class V> U m(V* p) { return *ptr = *p; }
+};
+
+int main()
+{
+  A<int> a;
+  short s = 0;
+  return a.m(&s);
+}
+#endif
+
+#ifdef TEST_KWSYS_CXX_HAS_FULL_SPECIALIZATION
+template <class T> struct A {};
+template <> struct A<int*>
+{
+  static int f() { return 0; }
+};
+int main() { return A<int*>::f(); }
+#endif
+
+#ifdef TEST_KWSYS_STL_HAS_ALLOCATOR_REBIND
+#include <memory>
+template <class T, class Alloc>
+void f(const T&, const Alloc&)
+{
+  typedef typename Alloc::template rebind<T>::other alloc_type;
+};
+int main()
+{
+  f(0, std::allocator<char>());
+  return 0;
+}
+#endif
+
 #ifdef TEST_KWSYS_STAT_HAS_ST_MTIM
 #include <sys/types.h>
 #include <sys/stat.h>
diff --git a/testhash.cxx b/testhash.cxx
new file mode 100644
index 00000000..0ca54e63
--- /dev/null
+++ b/testhash.cxx
@@ -0,0 +1,51 @@
+#include <kwsys/hash_map.hxx>
+#include <kwsys/hash_set.hxx>
+
+#include <kwsys/ios/iostream>
+
+#if defined(_MSC_VER)
+# pragma warning (disable:4786)
+#endif
+
+template class kwsys::hash_map<const char*, int>;
+template class kwsys::hash_set<int>;
+
+bool test_hash_map()
+{
+  typedef kwsys::hash_map<const char*, int> mtype;
+  mtype m;
+  const char* keys[] = {"hello", "world"};
+  m[keys[0]] = 1;
+  m.insert(mtype::value_type(keys[1], 2));
+  int sum = 0;
+  for(mtype::iterator mi = m.begin(); mi != m.end(); ++mi)
+    {
+    kwsys_ios::cout << "Found entry [" << mi->first << "," << mi->second << "]"
+                    << kwsys_ios::endl;
+    sum += mi->second;
+    }
+  return sum == 3;
+}
+
+bool test_hash_set()
+{
+  typedef kwsys::hash_set<int> stype;
+  stype s;
+  s.insert(1);
+  s.insert(2);
+  int sum = 0;
+  for(stype::iterator si = s.begin(); si != s.end(); ++si)
+    {
+    kwsys_ios::cout << "Found entry [" << *si << "]" << kwsys_ios::endl;
+    sum += *si;
+    }
+  return sum == 3;
+}
+
+int main()
+{
+  bool result = true;
+  result = test_hash_map() && result;
+  result = test_hash_set() && result;
+  return result? 0:1;
+}
-- 
GitLab