From 493dac3e9803f6ed6e9f68c16b7e1504ceb4dc59 Mon Sep 17 00:00:00 2001
From: Marco Clemencic <marco.clemencic@cern.ch>
Date: Thu, 19 Nov 2015 11:39:29 +0100
Subject: [PATCH 01/10] first attempt in removing KeyedObjectManager

---
 .../src/DataSvc/StoreExplorerAlg.cpp          |  11 +-
 GaudiExamples/GaudiExamples/MyTrack.h         |   2 +-
 GaudiExamples/src/IO/dict.xml                 |  32 +-
 GaudiKernel/GaudiKernel/KeyedContainer.h      | 267 +++----
 GaudiKernel/GaudiKernel/KeyedObject.h         |   5 -
 GaudiKernel/GaudiKernel/KeyedObjectManager.h  | 102 ---
 GaudiKernel/GaudiKernel/KeyedTraits.h         |   8 +-
 GaudiKernel/src/Lib/KeyedObjectManager.cpp    | 664 ------------------
 GaudiKernel/src/Lib/KeyedTraits.cpp           |  26 +
 9 files changed, 145 insertions(+), 972 deletions(-)
 delete mode 100644 GaudiKernel/GaudiKernel/KeyedObjectManager.h
 delete mode 100644 GaudiKernel/src/Lib/KeyedObjectManager.cpp
 create mode 100644 GaudiKernel/src/Lib/KeyedTraits.cpp

diff --git a/GaudiCommonSvc/src/DataSvc/StoreExplorerAlg.cpp b/GaudiCommonSvc/src/DataSvc/StoreExplorerAlg.cpp
index d67e97733b..26e190f759 100644
--- a/GaudiCommonSvc/src/DataSvc/StoreExplorerAlg.cpp
+++ b/GaudiCommonSvc/src/DataSvc/StoreExplorerAlg.cpp
@@ -120,6 +120,7 @@ public:
         const CLID id = p->clID();
         log << " [" << numObj << "]";
         if ( m_testAccess )  {
+          using ko_t = KeyedObject<int>;
           CLID idd = id>>16;
           switch(idd) {
             case CLID_ObjectList>>16:                /* ObjectList    */
@@ -129,14 +130,14 @@ public:
               access((ObjectVector<ContainedObject>*)base);
               break;
             case (CLID_ObjectVector+0x00030000)>>16: /* Keyed Map     */
-              access((KeyedContainer<KeyedObject<int>,Containers::Map>*)base);
+              access((KeyedContainer<ko_t,std::map<ko_t::key_type, ko_t*>>*)base);
               break;
             case (CLID_ObjectVector+0x00040000)>>16: /* Keyed Hashmap */
-              access((KeyedContainer<KeyedObject<int>,Containers::HashMap>*)base);
-              break;
-            case (CLID_ObjectVector+0x00050000)>>16: /* Keyed array   */
-              access((KeyedContainer<KeyedObject<int>,Containers::Array>*)base);
+              access((KeyedContainer<ko_t,std::unordered_map<ko_t::key_type, ko_t*>>*)base);
               break;
+            //case (CLID_ObjectVector+0x00050000)>>16: /* Keyed array   */
+            //  access((KeyedContainer<ko_t,Containers::Array>*)base);
+            //  break;
           }
         }
       }
diff --git a/GaudiExamples/GaudiExamples/MyTrack.h b/GaudiExamples/GaudiExamples/MyTrack.h
index 684191171c..40bd8b20da 100644
--- a/GaudiExamples/GaudiExamples/MyTrack.h
+++ b/GaudiExamples/GaudiExamples/MyTrack.h
@@ -56,7 +56,7 @@ namespace Gaudi
       typedef ObjectVector<MyTrack>                        Container ;
 #else
       /// the actual type of container in TES
-      typedef KeyedContainer<MyTrack, Containers::HashMap> Container ;
+      typedef KeyedContainer<MyTrack>                      Container ;
 #endif
       // ======================================================================
     protected:
diff --git a/GaudiExamples/src/IO/dict.xml b/GaudiExamples/src/IO/dict.xml
index 17cf77dd48..dbbe754548 100644
--- a/GaudiExamples/src/IO/dict.xml
+++ b/GaudiExamples/src/IO/dict.xml
@@ -7,33 +7,33 @@
   <class name="Gaudi::Examples::MyVertex"    id="00000164-0000-0000-0000-000000000000"/>
 
   <class name="SmartRef<Gaudi::Examples::Event>">
-    <field name="m_target" transient="true"/>  
+    <field name="m_target" transient="true"/>
   </class>
 
   <class name="SmartRef<Gaudi::Examples::Collision>">
-    <field name="m_target" transient="true"/>  
+    <field name="m_target" transient="true"/>
   </class>
   <class name="SmartRefVector<Gaudi::Examples::Collision>">
-    <field name="m_data" transient="true"/>  
-    <field name="m_contd" transient="true"/>  
+    <field name="m_data" transient="true"/>
+    <field name="m_contd" transient="true"/>
   </class>
   <class name="std::vector<SmartRef<Gaudi::Examples::Collision> >"/>
 
   <class name="SmartRef<Gaudi::Examples::MyTrack>">
-    <field name="m_target" transient="true"/>  
+    <field name="m_target" transient="true"/>
   </class>
   <class name="SmartRefVector<Gaudi::Examples::MyTrack>">
-    <field name="m_data" transient="true"/>  
-    <field name="m_contd" transient="true"/>  
+    <field name="m_data" transient="true"/>
+    <field name="m_contd" transient="true"/>
   </class>
   <class name="std::vector<SmartRef<Gaudi::Examples::MyTrack> >"/>
 
   <class name="SmartRef<Gaudi::Examples::MyVertex>">
-    <field name="m_target" transient="true"/>  
+    <field name="m_target" transient="true"/>
   </class>
   <class name="SmartRefVector<Gaudi::Examples::MyVertex>">
-    <field name="m_data" transient="true"/>  
-    <field name="m_contd" transient="true"/>  
+    <field name="m_data" transient="true"/>
+    <field name="m_contd" transient="true"/>
   </class>
   <class name="std::vector<SmartRef<Gaudi::Examples::MyVertex> >"/>
 
@@ -45,12 +45,12 @@
   <class name="std::vector<KeyedObject<int>* >"/>
   <!-- <class name="std::vector<KeyedObject<long int>* >"/> -->
 
-  <class name="KeyedContainer<Gaudi::Examples::MyTrack,Containers::KeyedObjectManager<Containers::hashmap> >" id="00060163-0000-0000-0000-000000000000">
-    <field name="m_cont" transient="true"/>  
-    <field name="m_random" transient="true"/>  
+  <class name="KeyedContainer<Gaudi::Examples::MyTrack>" id="00060163-0000-0000-0000-000000000000">
+    <field name="m_random" transient="true"/>
+    <field name="m_keySeq" transient="true"/>
   </class>
-  <class name="KeyedContainer<Gaudi::Examples::MyVertex,Containers::KeyedObjectManager<Containers::hashmap> >" id="00060164-0000-0000-0000-000000000000">
-    <field name="m_cont" transient="true"/>  
-    <field name="m_random" transient="true"/>  
+  <class name="KeyedContainer<Gaudi::Examples::MyVertex>" id="00060164-0000-0000-0000-000000000000">
+    <field name="m_random" transient="true"/>
+    <field name="m_keySeq" transient="true"/>
   </class>
 </lcgdict>
diff --git a/GaudiKernel/GaudiKernel/KeyedContainer.h b/GaudiKernel/GaudiKernel/KeyedContainer.h
index 9560552f6d..5d3f831855 100644
--- a/GaudiKernel/GaudiKernel/KeyedContainer.h
+++ b/GaudiKernel/GaudiKernel/KeyedContainer.h
@@ -4,15 +4,14 @@
 // Include files
 #include <iterator>
 #include <algorithm>
-
-namespace GaudiDict  {
-  template <class T> struct KeyedContainerDict;
-}
+#include <map>
+#include <unordered_map>
 
 // Framework include files
 #include "GaudiKernel/ObjectContainerBase.h"
-#include "GaudiKernel/KeyedObjectManager.h"
+#include "GaudiKernel/KeyedTraits.h"
 #include "GaudiKernel/KeyedObject.h"
+#include "GaudiKernel/GaudiException.h"
 
 // Forward declarations
 // template <class T, class M> class KeyedContainer;
@@ -23,6 +22,19 @@ namespace GaudiDict  {
 #define FORCE_INLINE inline
 #endif
 
+template<typename T>
+struct CLID_KC_Vector_Offset {};
+
+template <class K, class V>
+struct CLID_KC_Vector_Offset<std::map<K,V>> {
+  constexpr static const CLID value = 0x00030000 + CLID_ObjectVector;
+};
+
+template <class K, class V>
+struct CLID_KC_Vector_Offset<std::unordered_map<K,V>> {
+  constexpr static const CLID value = 0x00040000 + CLID_ObjectVector;
+};
+
 /** template class KeyedContainer, KeyedContainer.h
  *
  *  This class represents a container, where the contained objects
@@ -59,16 +71,14 @@ namespace GaudiDict  {
  *  @version  1.0
  *
  */
-template <class DATATYPE, class MAPPING=Containers::HashMap >
+template <class DATATYPE, class MAPPING=std::unordered_map<typename DATATYPE::key_type, DATATYPE*>>
 class GAUDI_API KeyedContainer: public ObjectContainerBase
 {
-  friend struct GaudiDict::KeyedContainerDict<DATATYPE>;
-
 public:
   /// Definition of the contained object type
   typedef DATATYPE                                  contained_type;
   /// Definition of the implementing container type
-  typedef MAPPING                                   container_type;
+  typedef MAPPING                                   map_type;
 
   /** General container specific type definitions.
       The following type definitions are generic to most STL containers
@@ -101,74 +111,39 @@ private:
   /** Traits class definition. Specializing traits allows to specialize the
    *  container implementation for special needs.
    */
-  typedef typename Containers::traits<container_type, contained_type> traits;
+  typedef typename Containers::traits<contained_type> traits;
 
   /**@name Implementation helpers.
   */
   //@{
-  /// Map container to facilitate object access by key.
-  container_type m_cont;
   /// Array to allow sequential access to the object (can be ordered).
   seq_type       m_sequential;
-  /// Array to allow random access to objects (not exposed)
-  seq_type*      m_random;
+  /// Map container to facilitate object access by key.
+  map_type       m_random;
+
+  /// Keep track of the highest inserted key (for sparse containers)
+  key_type       m_keySeq{-1};
 
   /// Internal function to access objects within the container
-#ifdef CHECK_KEYED_CONTAINER
   value_type i_object(const key_type& k) const  {
-    if ( 0 == m_cont.isDirect() )  {
-      if ( traits::checkBounds(m_random, k) )  {
-        value_type p = *(m_random->begin()+traits::hash(k));
-        if ( traits::checkKey(p, k) ) {
-          return p;
-        }
-      }
-      return 0;
-    }
-    value_type p = value_type(m_cont.object(traits::hash(k)));
-    return traits::checkKey(p, k) ? p : 0;
-  }
-#else
-  FORCE_INLINE value_type i_object(const key_type& k) const  {
-    return 0==m_cont.isDirect()
-      ? value_type(*(m_random->begin()+traits::hash(k)))
-      : value_type(m_cont.object(traits::hash(k)));
+    auto it = m_random.find(traits::hash(k));
+    return it == m_random.end() ? nullptr : it->second;
   }
-#endif
+
   /// Internal function to erase an object from the container
-  long i_erase(const_reference v, const key_type& k)   {
-    value_type p = value_type(m_cont.erase(traits::hash(k), v));
-    if ( p )    {
-      if ( p->parent() == this )  {
-        p->setParent(0);
-      }
+  long i_erase(const key_type& k, const_reference v=nullptr) {
+    auto kv = m_random.find(traits::hash(k));
+    if (kv != m_random.end() && (v && kv->second == v)) {
+      auto it = std::find(m_sequential.begin(), m_sequential.end(), kv->second);
+      m_sequential.erase(it);
+      auto p = const_cast<reference>(kv->second);
+      if (p->parent() == this) p->setParent(nullptr);
+      return traits::release(p) <= 0 ? (long) Containers::OBJ_ERASED
+                                     : (long) Containers::OBJ_DELETED;
     }
-    return traits::release(p) <= 0 ? (long) Containers::OBJ_ERASED
-                                   : (long) Containers::OBJ_DELETED;
+    return static_cast<long>(Containers::OBJ_NOT_FOUND);
   }
 
-  /// Internal functor for insertion of objects
-  struct _InsertRelease {
-    KeyedContainer<DATATYPE,MAPPING>* m_obj;
-    _InsertRelease(KeyedContainer<DATATYPE,MAPPING>* p) : m_obj(p) {}
-    void operator()(value_type p) {
-      m_obj->insert(p);
-      traits::release(p);
-    }
-  };
-
-  /// Internal functor for insertion of objects
-  struct _RemoveRelease {
-    ObjectContainerBase* m_obj;
-    _RemoveRelease(ObjectContainerBase* p) : m_obj(p) {}
-    void operator()(value_type p) {
-      const ObjectContainerBase* par = p->parent();
-      if ( par == m_obj )  {
-        p->setParent(0);
-      }
-      traits::release(p);
-    }
-  };
   //@}
 
 public:
@@ -176,13 +151,15 @@ public:
   */
   //@{
   /// Standard Constructor
-  KeyedContainer(void)
+  KeyedContainer() = default;
+  KeyedContainer(KeyedContainer&& other):
+      m_sequential(std::move(other.m_sequential)),
+      m_random(std::move(other.m_random)),
+      m_keySeq(other.m_keySeq)
   {
-    // avoid problems with strict-aliasing rules
-    seq_type** rptr = &m_random;
-    seq_type*  sptr = &m_sequential;
-    m_cont.setup((void*)sptr,(void**)rptr);
+    for(auto obj: m_sequential) obj->setParent(this);
   }
+  KeyedContainer(const KeyedContainer&) = delete;
   /// Destructor
   virtual ~KeyedContainer();
   //@}
@@ -195,9 +172,9 @@ public:
   /// Retrieve class ID
   virtual const CLID& clID() const      {              return this->classID(); }
   /// Retrieve class ID
-  static const CLID& classID()          {
-    static CLID clid = contained_type::classID() + container_type::classID();
-    return clid;
+  static const CLID& classID() {
+    static CLID cid= DATATYPE::classID() + CLID_KC_Vector_Offset<MAPPING>::value;
+    return cid;
   }
   //@}
 
@@ -274,9 +251,9 @@ public:
   /// For consistency with STL: check if container is empty
   bool empty() const                    {      return m_sequential.empty();   }
   /// Reserve place for "value" objects in the container.
-  void reserve(size_type value)         {      m_cont.reserve(value);          }
+  void reserve(size_type value)         {      m_sequential.reserve(value);   }
   /// Clear the entire content and erase the objects from the container
-  void clear()                          {      erase(begin(), end());          }
+  void clear()                          {      erase(begin(), end());         }
   /** Retrieve the full content of the object container by reference.
    *  Returned is the random access container if in sequntial direct
    *  access mode. Otherwise the sequential access container is returned
@@ -374,7 +351,7 @@ public:
    *                                   The object was deleted, because
    *                                   its reference count was zero.
    */
-  long erase(const key_type& kval)  { return i_erase(0, kval);  }
+  long erase(const key_type& kval)  { return i_erase(kval);  }
 
   /** Remove/erase object (identified by pointer value) from the container.
    *  This member function removes an object, which is identified by its
@@ -397,7 +374,7 @@ public:
    *                                   its reference count was zero.
    */
   long erase(const value_type val) {
-    return (val) ? i_erase(val, val->key()) : (long) Containers::OBJ_NOT_FOUND;
+    return (val) ? i_erase(val->key(), val) : (long) Containers::OBJ_NOT_FOUND;
   }
 
   /** Remove/erase object (identified by iterator) from the container.
@@ -430,7 +407,7 @@ public:
    *  @param    pos_stop    Starting iterator of the range to be removed.
    *  @param    use_temp    Flag to indicate that a temporary arry should be used.
    */
-  void erase(iterator pos_start, iterator pos_stop, bool use_temp=false);
+  void erase(iterator pos_start, iterator pos_stop);
 
   /** Insert entry to the container with a valid key.
    *  This member function inserts an element, which is identified by its
@@ -445,12 +422,12 @@ public:
    *
    *  @param    val   Reference to object to be inserted into the container.
    *                  The object reference may NOT be NULL.
-   *  @param   kval   Key to identify the object within the container.
+   *  @param    k     Key to identify the object within the container.
    *  @return         Key, which was used to index the object within the
    *                  container. If the operation is not
    *                  successful, an exception is thrown.
    */
-  const key_type& insert(const value_type val, const key_type& kval);
+  const key_type& insert(const value_type val, const key_type& k);
 
   /** Insert entry to the container with automatic key assignment.
    *  This member function inserts an element, which is identified by its
@@ -489,35 +466,18 @@ public:
 template <class DATATYPE, class MAPPING> inline
 KeyedContainer<DATATYPE, MAPPING>::~KeyedContainer()
 {
-  erase(begin(), end());
-  m_cont.clear();
+  clear();
 }
 
 // Configure direct access
 template <class DATATYPE, class MAPPING> inline
 StatusCode KeyedContainer<DATATYPE, MAPPING>::update()
 {
-  int count = 0;
-  m_cont.clearDirect();
-  typename seq_type::iterator i = m_sequential.begin();
-  typename seq_type::iterator s = m_sequential.end();
-  for ( ; i != s; i++ )  {
-    typename seq_type::value_type v = *i;
-    if ( v )  {
-      if ( !v->hasKey() ) {
-        traits::setKey(v, v->key());
-        traits::addRef(v);
-      }
-      long k0 = traits::hash(v->key());
-      if(m_cont.insertDirect(this, v, v, k0) == Containers::OBJ_INSERTED)   {
-      }
-    }
-    else  {
-      ++count;
-    }
-  }
-  if ( count > 0 )  {
-    Containers::cannotInsertToContainer();
+  m_keySeq = -1;
+  for(auto obj: m_sequential) {
+    const auto k = obj->key();
+    m_random.insert({traits::hash(k), obj});
+    if (m_keySeq < k) m_keySeq = k;
   }
   return StatusCode::SUCCESS;
 }
@@ -527,28 +487,34 @@ StatusCode KeyedContainer<DATATYPE, MAPPING>::update()
 template <class DATATYPE, class MAPPING> inline
 const std::vector<const ContainedObject*>*
 KeyedContainer<DATATYPE, MAPPING>::containedObjects() const  {
-  return (const std::vector<const ContainedObject*>*)
-    ((0==m_cont.isDirect()) ? m_random : &m_sequential);
+  throw GaudiException("Method not implemented",
+                       "KeyedContainer::containedObjects()",
+                       StatusCode::FAILURE);
+  return nullptr;
 }
 
 template <class DATATYPE, class MAPPING> inline
 const typename KeyedContainer<DATATYPE, MAPPING>::key_type&
 KeyedContainer<DATATYPE, MAPPING>::insert(const value_type val,
-                                          const key_type& kval)
+                                          const key_type& k)
 {
-  if ( val )    {
-    long k0 = traits::hash(kval);
-    if ( !val->hasKey() || (traits::hash(val->key()) == k0) )    {
-      if(m_cont.insert(this,val,val,k0) == Containers::OBJ_INSERTED)   {
-        if ( !val->hasKey() ) traits::setKey(val, kval);
-        traits::addRef(val);
-        return val->key();
-      }
+  if (val && ((!val->hasKey()) || (val->key() == k))) {
+    // to attempt an insertion, we need an object either
+    // without key or with the same key we pass
+    auto it = m_random.find(traits::hash(k));
+    if (it == m_random.end()) {
+      traits::setKey(val, k);
+      m_keySeq = std::max(k, m_keySeq);
+      m_random.insert({traits::hash(k), val});
+      m_sequential.push_back(val);
+      val->setParent(this);
+      traits::addRef(val);
+      return k;
     }
   }
   // Cannot insert object...indicate bad object insertion...
   Containers::cannotInsertToContainer();
-  return val->key();
+  return k;
 }
 
 // Insert object
@@ -556,20 +522,9 @@ template <class DATATYPE, class MAPPING> //inline
 const typename KeyedContainer<DATATYPE, MAPPING>::key_type&
 KeyedContainer<DATATYPE, MAPPING>::insert(const value_type val)
 {
-  if ( 0 != val )   {
-    if ( val->hasKey() )   {
-      if (m_cont.insert(this,val,val,traits::hash(val->key()))
-          == Containers::OBJ_INSERTED)   {
-        traits::addRef(val);
-        return val->key();
-      }
-    }
-    long k0;
-    if ( m_cont.insert(this, val, val, &k0) == Containers::OBJ_INSERTED )   {
-      traits::setKey(val, traits::makeKey(k0));
-      traits::addRef(val);
-      return val->key();
-    }
+  if (val) {
+    return val->hasKey() ? insert(val, val->key())
+                         : insert(val, ++m_keySeq);
   }
   // Cannot insert object...indicate bad object insertion...
   Containers::cannotInsertToContainer();
@@ -589,14 +544,9 @@ template <class DATATYPE, class MAPPING> inline
 typename KeyedContainer<DATATYPE, MAPPING>::size_type KeyedContainer<DATATYPE, MAPPING>::containedObjects
 (std::vector<ContainedObject*>& vec) const
 {
-  typename seq_type::const_iterator i = m_sequential.begin();
-  typename seq_type::const_iterator s = m_sequential.end();
   vec.clear();
   vec.reserve(size());
-  for ( ; i != s; i++ )  {
-    ContainedObject* p = const_cast<typename seq_type::value_type>(*i);
-    vec.push_back(p);
-  }
+  for (auto o: m_sequential) vec.push_back(o);
   return vec.size();
 }
 
@@ -612,54 +562,23 @@ template <class DATATYPE, class MAPPING> inline
 long KeyedContainer<DATATYPE, MAPPING>::remove(ContainedObject* p)
 {
   contained_type* p1 = dynamic_cast<contained_type*>(p);
-  if ( p1 )    {  // Normal case; object still fully intact
-    return this->erase(p1);
-  }
-  else if ( p )   {
-    const ObjectContainerBase* par = p->parent();
-    // The following should never occur: object is in a funny state,
-    // Because the parent was explicitly set to NULL in the
-    // KeyeObject destructor.
-    // - It cannot be a KeyedObject:  It would not have a parent
-    // - Still the parent is present: We are not in the destructor
-    //                                of KeyedObject
-    if ( par )  {
-      Containers::invalidContainerOperation();
-    }
-    return m_cont.erase(0, p)==0 ? (long) Containers::OBJ_ERASED
-                                 : (long) Containers::OBJ_NOT_FOUND;
-  }
-  return (long) Containers::OBJ_NOT_FOUND;
+  return p1 ? this->erase(p1) : (long) Containers::OBJ_NOT_FOUND;
 }
 
 template <class DATATYPE, class MAPPING> inline
 void
 KeyedContainer<DATATYPE, MAPPING>::erase(iterator start_pos,
-                                         iterator stop_pos,
-                                         bool use_tmp)
+                                         iterator stop_pos)
 {
-  bool is_start = start_pos == m_sequential.begin();
-  bool is_stop  = stop_pos  == m_sequential.end();
-  if ( is_start && is_stop )  {
-    // Nothing special. Taken care of by Keyed object manager
-  }
-  else if ( is_start || is_stop || use_tmp )  {
-    std::vector<DATATYPE*> tmp(m_sequential.begin(), start_pos);
-    tmp.insert(tmp.end(), stop_pos, m_sequential.end());
-    std::for_each(tmp.begin(), tmp.end(), traits::addRef);
-    this->erase(m_sequential.begin(), m_sequential.end());
-    std::for_each(tmp.begin(), tmp.end(), _InsertRelease(this));
-    return;
-  }
-  std::for_each(start_pos, stop_pos, _RemoveRelease(this));
-  seq_type *sptr = &m_sequential; // avoid problems with strict-aliasing rules
-  std::vector<void*>* v = (std::vector<void*>*)sptr;
-  std::vector<void*>::iterator i1 =
-    v->begin() + std::distance(m_sequential.begin(), start_pos);
-  std::vector<void*>::iterator i2 =
-    v->begin() + std::distance(m_sequential.begin(), stop_pos);
-  m_cont.erase(i1, i2);
+  std::for_each(start_pos, stop_pos,
+    [this](value_type &v) {
+      m_random.erase(v->key());
+      if (v->parent() == this) v->setParent(nullptr);
+      traits::release(v);
+  });
+  m_sequential.erase(start_pos, stop_pos);
 }
 
+
 #undef FORCE_INLINE
 #endif // GAUDIKERNEL_KEYEDCONTAINER_H
diff --git a/GaudiKernel/GaudiKernel/KeyedObject.h b/GaudiKernel/GaudiKernel/KeyedObject.h
index 1ac071527f..f5ec001be2 100644
--- a/GaudiKernel/GaudiKernel/KeyedObject.h
+++ b/GaudiKernel/GaudiKernel/KeyedObject.h
@@ -1,10 +1,6 @@
 #ifndef GAUDIKERNEL_KEYEDOBJECT_H
 #define GAUDIKERNEL_KEYEDOBJECT_H
 
-namespace GaudiDict  {
-  template <class T> struct KeyedObjectDict;
-}
-
 // Framework include files
 #include "GaudiKernel/ContainedObject.h"
 #include "GaudiKernel/KeyedTraits.h"
@@ -26,7 +22,6 @@ namespace GaudiDict  {
  */
 template < class KEY >
 class GAUDI_API KeyedObject: public ContainedObject {
-  friend struct GaudiDict::KeyedObjectDict<KEY>;
 public:
   /// Definition of the key-type to access object
   typedef KEY key_type;
diff --git a/GaudiKernel/GaudiKernel/KeyedObjectManager.h b/GaudiKernel/GaudiKernel/KeyedObjectManager.h
deleted file mode 100644
index f62931e820..0000000000
--- a/GaudiKernel/GaudiKernel/KeyedObjectManager.h
+++ /dev/null
@@ -1,102 +0,0 @@
-#ifndef GAUDIKERNEL_KEYEDOBJECTMANAGER_H
-#define GAUDIKERNEL_KEYEDOBJECTMANAGER_H
-
-// Framework include files
-#include "GaudiKernel/Kernel.h"
-#include "GaudiKernel/ClassID.h"
-#include "GaudiKernel/KeyedTraits.h"
-
-// STL includes
-#include <vector>
-
-// Forward declarations
-class ObjectContainerBase;
-class ContainedObject;
-
-/** Containers namespace
-*/
-namespace Containers   {
-
-  /// Object manipulator type definition
-  typedef long (*MANIPULATOR)(void*);
-  /// Parametrisation class for hashmap-like implementation.
-  struct GAUDI_API hashmap;
-  /// Parametrisation class for map-like implementation.
-  struct GAUDI_API map;
-  /// Parametrisation class for redirection array - like implementation.
-  struct GAUDI_API array;
-  /// Parametrisation class for vector-like implementation.
-  struct GAUDI_API vector;
-
-  /** KeyedObjectManager
-   *  Class to manage keyed objects. This class is instantiated for two
-   *  container types: map and hashmap. Other types are possible,
-   *  but currently not supported. Other implementations may be achieved
-   *  by specializing the SETUP class.
-   *
-   *  As an example below the specialization for a vector like
-   *  implementation is shown.
-   *
-   *  @author   M.Frank CERN/LHCb
-   *  @version  1.0
-   *
-   */
-  template <class SETUP>
-  class GAUDI_API KeyedObjectManager    {
-  private:
-    typedef std::vector<void*> seq_type;
-    /// Container holding array like container
-    seq_type*       m_seq;
-    /// Dirty flag
-    mutable long    m_direct;
-    mutable long    m_keyCtxt;
-    union {
-      /// Buffer space to hold keyed container
-      char          buffer[128];
-      SETUP*        s;
-    } m_setup;
-
-    /// Callback when the container becomes dirty
-    void onDirty()  const;
-
-  public:
-    /// Standard Constructor
-    KeyedObjectManager();
-    /// Standard Destructor
-    virtual ~KeyedObjectManager();
-    /// Clear all direct access fields
-    void clearDirect();
-    /// Insert element into direct access map
-    long insertDirect(ObjectContainerBase* b,ContainedObject* c,void* o, long k);
-    /// Check if the container is dirty
-    long isDirect() const {      return m_direct;    }
-    /// Retrieve object identified by a key from the container
-    void* object(long key)  const;
-    /// Insert new object into container
-    long insert(ObjectContainerBase* b,ContainedObject* c,void* o, long* k);
-    /// Insert new object into container
-    long insert(ObjectContainerBase* b,ContainedObject* c,void* o,long k);
-    /// Remove object from container (very inefficient if key is invalid)
-    void* erase(long key, const void* obj);
-    /// Remove object by sequential iterators
-    long erase(seq_type::iterator beg, seq_type::iterator end);
-    /// Reserve buffer space
-    void reserve(long size);
-    /// Clear content of the vector
-    void clear();
-    /// Setup of the Map and the parent object
-    void setup(void* seq, void** rndm);
-    /// Access CLID for this type of container.
-    static CLID classID();
-  };
-
-  /// Forward declaration of specialized std::map-like object manager
-  typedef KeyedObjectManager< map >     Map;
-  /// Forward declaration of specialized std::hashmap-like object manager
-  typedef KeyedObjectManager< hashmap > HashMap;
-  /// Forward declaration of specialized std::vector-like object manager
-  typedef KeyedObjectManager< vector >  Vector;
-  /// Forward declaration of specialized redirection array object manager
-  typedef KeyedObjectManager< array >   Array;
-}
-#endif // GAUDIKERNEL_KEYEDOBJECTMANAGER_H
diff --git a/GaudiKernel/GaudiKernel/KeyedTraits.h b/GaudiKernel/GaudiKernel/KeyedTraits.h
index fd358433f3..15fb5f33d8 100644
--- a/GaudiKernel/GaudiKernel/KeyedTraits.h
+++ b/GaudiKernel/GaudiKernel/KeyedTraits.h
@@ -27,11 +27,9 @@ namespace Containers    {
   // Forward declarations
 
   /// Container traits class
-  template <class CONTAINER, class DATATYPE>  struct traits;
+  template <class DATATYPE>  struct traits;
   /// Key traits class
-  template <class KEY>                        struct key_traits;
-  /// Object manager class
-  template <class SETUP>                      class  KeyedObjectManager;
+  template <class KEY>       struct key_traits;
 
   /** Function to be called to indicate that an object cannot be inserted
       to the container. Internally an exception is thrown.                    */
@@ -102,7 +100,7 @@ namespace Containers    {
       @author   M.Frank CERN/LHCb
       @version  1.0
   */
-  template < class CONTAINER, class DATATYPE >
+  template < class DATATYPE >
   struct traits : public key_traits < typename DATATYPE::key_type >
   {
     /// Allow to check the access to container elements for consistency
diff --git a/GaudiKernel/src/Lib/KeyedObjectManager.cpp b/GaudiKernel/src/Lib/KeyedObjectManager.cpp
deleted file mode 100644
index 240d443a4f..0000000000
--- a/GaudiKernel/src/Lib/KeyedObjectManager.cpp
+++ /dev/null
@@ -1,664 +0,0 @@
-// Include files
-#include "GaudiKernel/Kernel.h"
-#include "GaudiKernel/GaudiException.h"
-#include "GaudiKernel/ContainedObject.h"
-#include "GaudiKernel/KeyedObjectManager.h"
-#include <algorithm>
-#include <map>
-#include "GaudiKernel/HashMap.h"
-
-namespace Containers    {
-  struct hashmap   {
-    typedef GaudiUtils::HashMap<long, void*> map_type;
-    map_type               m;
-    std::vector<void*>     v;
-    bool insert(void* obj, long key)    {
-      auto p = m.insert(map_type::value_type(key,obj));
-      return p.second;
-    }
-  };
-  struct map   {
-    typedef std::map<long, void*>      map_type;
-    map_type                m;
-    std::vector<void*>      v;
-    bool insert(void* obj, long key)    {
-      auto p = m.insert(map_type::value_type(key,obj));
-      return p.second;
-    }
-  };
-  struct array {
-    typedef std::vector<long> map_type;
-    /// Indirection array
-    std::vector<long>         m_idx;
-    /// Direct access array
-    std::vector<void*>        v;
-    struct decrement   {
-      long m_min;
-      decrement(long m) : m_min(m) {}
-      bool operator()(long& j)  const {
-        if ( j > m_min ) --j;
-        return true;
-      }
-    };
-  };
-  struct vector {
-    typedef std::vector<void*>  map_type;
-    /// Direct access array
-    std::vector<void*>          v;
-  };
-
-  template <class CONT>
-  class find   {
-    const void* m_obj;
-    typedef typename CONT::value_type v_type;
-  public:
-    find(const void* o) : m_obj(o) {}
-    bool operator()(const void* cmp)  const {
-      return cmp == m_obj;
-    }
-    bool operator()(const v_type& cmp)  const {
-      return (*this)(cmp.second);
-    }
-  };
-}
-void Containers::cannotAssignObjectKey()   {
-  throw GaudiException("Cannot assign key to keyed object! Object already has a key.",
-                       "KeyedObject",
-                       0);
-}
-void Containers::cannotInsertToContainer()   {
-  throw GaudiException("Cannot insert element to Keyed Container!",
-                       "KeyedContainer",
-                       0);
-}
-
-void Containers::containerIsInconsistent()   {
-  throw GaudiException("Keyed Container structures are inconsistent - severe problem!",
-                       "KeyedContainer",
-                       0);
-}
-
-void Containers::invalidContainerOperation()   {
-  throw GaudiException("Keyed Container cannot satisfy request - severe problem!",
-                       "KeyedContainer",
-                       0);
-}
-
-template <class T>
-Containers::KeyedObjectManager<T>::KeyedObjectManager()
-: m_seq(nullptr), m_direct(0)
-{
-  if ( sizeof(typename T::map_type) > sizeof(m_setup.buffer) )    {
-    throw GaudiException("Basic STL contaier sizes are incompatible",
-                         "KeyedContainer",
-                         0);
-  }
-  m_setup.s = ::new(m_setup.buffer+sizeof(m_setup.s)) T();
-  m_keyCtxt = -1;
-}
-
-template <class T>
-Containers::KeyedObjectManager<T>::~KeyedObjectManager()
-{
-  m_setup.s->~T();
-}
-
-/// Setup of the Map and the parent object
-template <class T> void
-Containers::KeyedObjectManager<T>::setup(void* seq, void** rndm)
-{
-  m_seq = (seq_type*)seq;
-  *rndm = &m_setup.s->v;
-}
-
-template <class T>
-void Containers::KeyedObjectManager<T>::onDirty()   const  {
-  m_direct = 1;
-  for(int i = 0, stop = m_setup.s->v.size(); i < stop; i++ )   {
-    m_setup.s->insert(*(m_setup.s->v.begin()+i), i);
-  }
-  m_setup.s->v.clear();
-}
-
-template <class T>
-long Containers::KeyedObjectManager<T>::insert(
-                                ObjectContainerBase* pBase,
-                                ContainedObject* pObject,
-                                void* obj,
-                                long* key)
-{
-  *key = ++m_keyCtxt;
-  return insert(pBase, pObject, obj, *key);
-}
-
-template <class T>
-long Containers::KeyedObjectManager<T>::insert(
-                                ObjectContainerBase* pBase,
-                                ContainedObject* pObject,
-                                void* obj,
-                                long key)
-{
-  /// Keep major key value
-  if ( key > m_keyCtxt )  {
-    m_keyCtxt = key;
-  }
-  if ( 1==m_direct )  {
-    if ( m_setup.s->insert(obj, key) )   {
-      if ( !pObject->parent() )  {
-        pObject->setParent(pBase);
-      }
-      m_seq->push_back(obj);
-      return OBJ_INSERTED;
-    }
-  }
-  else if ( key == long(m_setup.s->v.size()) )  {
-    m_setup.s->v.push_back(obj);
-    if ( !pObject->parent() )  {
-      pObject->setParent(pBase);
-    }
-    m_seq->push_back(obj);
-    return OBJ_INSERTED;
-  }
-  else  {
-    // Document is dirty now...
-    // need to copy all pointers from the vector to the map
-    onDirty();
-    return insert(pBase, pObject, obj, key);
-  }
-  cannotInsertToContainer();
-  return OBJ_CANNOT_INSERT;
-}
-
-template <class T>
-long Containers::KeyedObjectManager<T>::insertDirect(
-                                ObjectContainerBase* pBase,
-                                ContainedObject* pObject,
-                                void* obj,
-                                long key)
-{
-  /// Keep major key value
-  if ( key > m_keyCtxt )  {
-    m_keyCtxt = key;
-  }
-  if ( 1==m_direct )  {
-    if ( m_setup.s->insert(obj, key) )   {
-      if ( !pObject->parent() )  {
-        pObject->setParent(pBase);
-      }
-      return OBJ_INSERTED;
-    }
-  }
-  else if ( key == long(m_setup.s->v.size()) )  {
-    m_setup.s->v.push_back(obj);
-    if ( !pObject->parent() )  {
-      pObject->setParent(pBase);
-    }
-    return OBJ_INSERTED;
-  }
-  else  {
-    // Document is dirty now...
-    // need to copy all pointers from the vector to the map
-    onDirty();
-    return insertDirect(pBase, pObject, obj, key);
-  }
-  cannotInsertToContainer();
-  return OBJ_CANNOT_INSERT;
-}
-
-// Remove object from container
-template <class T>
-void* Containers::KeyedObjectManager<T>::erase(long  key,
-                                               const void* obj) {
-  typedef typename T::map_type MTYP;
-  typedef find<MTYP> FND;
-  if ( 1 == m_direct )   {
-    auto& m = m_setup.s->m;
-    auto i = (obj ? std::find_if(m.begin(),m.end(),FND(obj))
-                  : m_setup.s->m.find(key) );
-    if ( i != m_setup.s->m.end() )   {
-      void* o = i->second;
-      auto j = std::find(m_seq->begin(),m_seq->end(),o);
-      if ( j != m_seq->end() )   {
-        m_seq->erase(j);
-        m_setup.s->m.erase(i);
-        return o;
-      }
-    }
-    containerIsInconsistent();
-  }
-  onDirty();
-  return erase(key, obj);
-}
-
-template <class T>
-void* Containers::KeyedObjectManager<T>::object(long key)  const
-{
-  if ( 0 == m_direct )   onDirty();
-  auto i = m_setup.s->m.find(key);
-  if ( i != m_setup.s->m.end() )  return (*i).second;
-  return nullptr;
-}
-
-template <class T>
-void Containers::KeyedObjectManager<T>::reserve(long len)
-{
-  switch( m_direct )   {
-  case 1:
-    break;
-  case 0:
-    m_setup.s->v.reserve(len);
-    break;
-  default:
-    break;
-  }
-  m_seq->reserve(len);
-}
-
-template <class T>
-void Containers::KeyedObjectManager<T>::clear()
-{
-  clearDirect();
-  m_seq->clear();
-}
-
-template <class T>
-void Containers::KeyedObjectManager<T>::clearDirect()
-{
-  switch( m_direct )   {
-  case 1:
-    m_setup.s->m.clear();
-    break;
-  case 0:
-    m_setup.s->v.clear();
-    break;
-  default:
-    break;
-  }
-  m_direct = 0;
-  m_keyCtxt = -1;
-}
-
-// Remove object by sequential iterators
-template <class T>
-long Containers::KeyedObjectManager<T>::erase(seq_type::iterator beg,
-                                              seq_type::iterator end)
-{
-  typedef typename T::map_type MTYP;
-  typedef find<MTYP> FND;
-  if ( 0 == m_direct )    {
-    onDirty();
-    return erase(beg, end);
-  }
-  if ( beg == m_seq->begin() && end == m_seq->end() )   {
-    clear();
-  }
-  else  {
-    for ( auto j=beg; j != end; ++j)  {
-      auto& m = m_setup.s->m;
-      auto  i = std::find_if(m.begin(),m.end(),FND(*j));
-      if ( i != m_setup.s->m.end() ) {
-        m_setup.s->m.erase(i);
-        continue;
-      }
-      containerIsInconsistent();
-    }
-    m_seq->erase(beg, end);
-  }
-  return OBJ_ERASED;
-}
-
-namespace Containers {
-
-  /*  First specialize static methods and then instantiate templated class to appear as symbols in the library
-      This order in needed for gcc 4.0 (MacOSX) */
-
-  template<>
-  CLID KeyedObjectManager< Containers::map >::classID()   {
-    return CLID_ObjectVector+0x00030000;
-  }
-  template<>
-  CLID KeyedObjectManager< Containers::hashmap >::classID()   {
-    return CLID_ObjectVector+0x00040000;
-  }
-
-  template class KeyedObjectManager<Containers::hashmap>;
-  template class KeyedObjectManager<Containers::map>;
-}
-
-/*
- *
- *
- *  Inline code for indirection array implementation
- *
- */
-typedef Containers::array __A;
-
-namespace Containers {
-
-//__forceinline
-template<> void*
-KeyedObjectManager< __A >::object(long value) const
-{
-#ifdef CHECK_KEYED_CONTAINER
-  unsigned long siz = m_setup.s->m_idx.size();
-  if ( value >= 0 && size_t(value) < siz )  {
-    long ent =  *(m_setup.s->m_idx.begin()+value);
-    if ( ent >= 0 )  {
-      return *(m_setup.s->v.begin() + ent);
-    }
-  }
-  return nullptr;
-#else
-  return *(m_setup.s->v.begin() + (*(m_setup.s->m_idx.begin()+value)));
-#endif
-}
-
-template<>
-void KeyedObjectManager< __A >::onDirty()  const {
-  m_direct = 1;
-  m_setup.s->m_idx.reserve(m_setup.s->v.size()+1);
-  for(int i = 0, stop = m_setup.s->v.size(); i < stop; ++i)   {
-    if ( !m_setup.s->v[i] )  {
-      containerIsInconsistent();
-    }
-    m_setup.s->m_idx.push_back(i);
-  }
-}
-
-// Insert new object into container
-template<>
-long KeyedObjectManager< __A >::insert(ObjectContainerBase* b,
-                                                   ContainedObject* c,
-                                                   void* o,
-                                                   long* k)
-{
-  // auto key creation only possible for direct access!
-  if ( 0 == m_direct )    {
-    m_seq->push_back(o);
-    m_setup.s->v.push_back(o);
-    if ( !c->parent() ) c->setParent(b);
-    *k = ++m_keyCtxt;
-    return OBJ_INSERTED;
-  }
-  cannotInsertToContainer();
-  return OBJ_CANNOT_INSERT;
-}
-
-// Insert new object into container
-template<>
-long KeyedObjectManager< __A >::insert(ObjectContainerBase* b,
-                                                   ContainedObject* c,
-                                                   void* o,
-                                                   long k)
-{
-  if ( 0 == m_direct )    {
-    if ( k == m_keyCtxt+1 ) {
-      return insert(b, c, o, &k);
-    }
-    onDirty();
-    return insert(b, c, o, k);
-  }
-  /// Keep major key value
-  if ( k > m_keyCtxt ) m_keyCtxt = k;
-  /// Extend redirection array and insert
-  if ( k+1 > long(m_setup.s->m_idx.size()) )   {
-    m_setup.s->m_idx.resize(k+1, -1);
-  }
-  auto idx = m_setup.s->m_idx.begin()+k;
-  if ( *idx == -1 )  {
-    *idx = m_setup.s->v.size();
-    m_setup.s->v.push_back(o);
-    m_seq->push_back(o);
-    if ( !c->parent() ) c->setParent(b);
-    return OBJ_INSERTED;
-  }
-  cannotInsertToContainer();
-  return OBJ_CANNOT_INSERT;
-}
-
-// Insert new object into container
-template<> long
-KeyedObjectManager< __A >::insertDirect(ObjectContainerBase* b,
-						    ContainedObject* c,
-						    void* o,
-						    long k)
-{
-  if ( 0 == m_direct )    {
-    if ( k == m_keyCtxt+1 ) {
-      m_setup.s->v.push_back(o);
-      if ( !c->parent() ) c->setParent(b);
-      ++m_keyCtxt;
-      return OBJ_INSERTED;
-    }
-    onDirty();
-    return insertDirect(b, c, o, k);
-  }
-  /// Keep major key value
-  if ( k > m_keyCtxt ) m_keyCtxt = k;
-  /// Extend redirection array and insert
-  if ( k+1 > long(m_setup.s->m_idx.size()) )   {
-    m_setup.s->m_idx.resize(k+1, -1);
-  }
-  auto idx = m_setup.s->m_idx.begin()+k;
-  if ( *idx == -1 )  {
-    *idx = m_setup.s->v.size();
-    m_setup.s->v.push_back(o);
-    if ( !c->parent() ) c->setParent(b);
-    return OBJ_INSERTED;
-  }
-  cannotInsertToContainer();
-  return OBJ_CANNOT_INSERT;
-}
-
-// Clear content of the vector
-template<>
-void KeyedObjectManager< __A >::clearDirect() {
-  m_setup.s->v.clear();
-  m_setup.s->m_idx.clear();
-  m_direct = 0;
-  m_keyCtxt = -1;
-}
-
-// Remove object from container (very inefficient if key is invalid)
-template<>
-void* KeyedObjectManager< __A >::erase(long key,
-                                                   const void* obj)
-{
-  typedef std::vector<long> id_type;
-  typedef id_type::iterator id_iter;
-  if ( 0 == m_direct )    {
-    onDirty();
-    return erase(key, obj);
-  }
-  if ( obj )   {
-    id_type& idx = m_setup.s->m_idx;
-    for (auto & elem : idx)    {
-      auto j = m_setup.s->v.begin()+(elem);
-      auto k = std::find(m_seq->begin(),m_seq->end(),*j);
-      if ( *j == obj )   {
-        void* o = *j;
-        m_seq->erase(k);
-        m_setup.s->v.erase(j);
-        std::for_each(m_setup.s->m_idx.begin(),
-                      m_setup.s->m_idx.end(),
-                      array::decrement(elem));
-        elem = -1;
-        return o;
-      }
-    }
-  }
-  else if ( key >= 0 && key < long(m_setup.s->m_idx.size()) )   {
-    auto idx = m_setup.s->m_idx.begin()+key;
-    if ( *idx != -1 )   {
-      auto i = m_setup.s->v.begin()+(*idx);
-      if ( i == m_setup.s->v.end() )   {
-        containerIsInconsistent();
-      }
-      void* o = *i;
-      auto j=std::find(m_seq->begin(),m_seq->end(),o);
-      if ( j == m_seq->end() )   {
-        containerIsInconsistent();
-      }
-      m_seq->erase(j);
-      m_setup.s->v.erase(i);
-      std::for_each(m_setup.s->m_idx.begin(),
-                    m_setup.s->m_idx.end(),
-                    array::decrement(*idx));
-      *idx = -1;
-      return o;
-    }
-  }
-  containerIsInconsistent();
-  return nullptr;
-}
-
-// Remove object by sequential iterators
-template<>
-long KeyedObjectManager< __A >::erase(seq_type::iterator beg,
-                                                  seq_type::iterator end)
-{
-  typedef std::vector<long> id_type;
-  typedef id_type::iterator id_iter;
-  if ( beg == m_seq->begin() && end == m_seq->end() )   {
-    clear();
-    return OBJ_ERASED;
-  }
-  else if ( 0 == m_direct )    {
-    onDirty();
-    return erase(beg, end);
-  }
-  else  {
-    long cnt = 0, nobj = end-beg;
-    id_type& idx = m_setup.s->m_idx;
-    for (auto & elem : idx)    {
-      auto j = m_setup.s->v.begin()+(elem);
-      auto k = std::find(beg,end,*j);
-      if ( k != end )   {
-        m_setup.s->v.erase(j);
-        std::for_each(m_setup.s->m_idx.begin(),
-                      m_setup.s->m_idx.end(),
-                      array::decrement(elem));
-        elem = -1;
-        cnt++;
-        if ( cnt == nobj ) break;
-      }
-    }
-    m_seq->erase(beg, end);
-    if ( cnt != nobj )  {
-      containerIsInconsistent();
-    }
-    return OBJ_ERASED;
-  }
-  // cannot reach this point
-}
-
-template<>
-CLID KeyedObjectManager< __A >::classID()   {
-  return CLID_ObjectVector+0x00050000;
-}
-}
-template class Containers::KeyedObjectManager<__A>;
-/*
-  *
-  *
-  *  Implementation for objects with vector like access
-  *
-  *
-  **/
-typedef Containers::vector __V;
-
-namespace Containers {
-// Access single entry by long(integer) key
-template<>
-void* KeyedObjectManager< __V >::object(long /* value */) const
-{
-  invalidContainerOperation();
-  return nullptr;
-}
-
-template<>
-void KeyedObjectManager<__V>::onDirty()   const  {
-  invalidContainerOperation();
-}
-
-// Insert new object into container
-template<>
-long KeyedObjectManager< __V >::insert(ObjectContainerBase* b,
-                                                   ContainedObject* c,
-                                                   void* o,
-                                                   long* k)
-{
-  m_seq->push_back(o);
-  m_setup.s->v.push_back(o);
-  if ( !c->parent() ) c->setParent(b);
-  *k = (m_setup.s->v.size()-1);
-  return OBJ_INSERTED;
-}
-
-// Insert new object into container
-template<>
-long KeyedObjectManager< __V >::insert(ObjectContainerBase* b,
-                                                   ContainedObject* c,
-                                                   void* o,
-                                                   long k)
-{
-  if ( k == long(m_setup.s->v.size()) ) {
-    return insert(b, c, o, &k);
-  }
-  cannotInsertToContainer();
-  return OBJ_CANNOT_INSERT;
-}
-
-// Insert new object into container
-template<> long
-KeyedObjectManager< __V >::insertDirect(ObjectContainerBase* b,
-						    ContainedObject* c,
-						    void* o,
-						    long k)
-{
-  if ( k == long(m_setup.s->v.size()) ) {
-    m_setup.s->v.push_back(o);
-    if ( !c->parent() ) c->setParent(b);
-    return OBJ_INSERTED;
-  }
-  cannotInsertToContainer();
-  return OBJ_CANNOT_INSERT;
-}
-
-// Clear content of the vector
-template<>
-void KeyedObjectManager< __V >::clearDirect()  {
-  m_setup.s->v.clear();
-  m_direct = 0;
-  m_keyCtxt = -1;
-}
-
-// Remove object from container (very inefficient if key is invalid)
-template<> void*
-KeyedObjectManager< __V >::erase(long /* key */,
-                                             const void* /* obj */)
-{
-  invalidContainerOperation();
-  return nullptr;
-}
-
-// Remove object by sequential iterators
-template<>
-long KeyedObjectManager< __V >::erase(seq_type::iterator beg,
-                                                  seq_type::iterator end)
-{
-  if ( beg == m_seq->begin() && end == m_seq->end() )   {
-    clear();
-    return OBJ_ERASED;
-  }
-  invalidContainerOperation();
-  return OBJ_ERASED;
-}
-
-template<>
-CLID KeyedObjectManager< __V >::classID()   {
-  return CLID_ObjectVector+0x00060000;
-}
-
-}
-template class Containers::KeyedObjectManager<__V>;
diff --git a/GaudiKernel/src/Lib/KeyedTraits.cpp b/GaudiKernel/src/Lib/KeyedTraits.cpp
new file mode 100644
index 0000000000..91d9553cfe
--- /dev/null
+++ b/GaudiKernel/src/Lib/KeyedTraits.cpp
@@ -0,0 +1,26 @@
+// Include files
+#include "GaudiKernel/GaudiException.h"
+#include "GaudiKernel/KeyedTraits.h"
+
+void Containers::cannotAssignObjectKey()   {
+  throw GaudiException("Cannot assign key to keyed object! Object already has a key.",
+                       "KeyedObject",
+                       0);
+}
+void Containers::cannotInsertToContainer()   {
+  throw GaudiException("Cannot insert element to Keyed Container!",
+                       "KeyedContainer",
+                       0);
+}
+
+void Containers::containerIsInconsistent()   {
+  throw GaudiException("Keyed Container structures are inconsistent - severe problem!",
+                       "KeyedContainer",
+                       0);
+}
+
+void Containers::invalidContainerOperation()   {
+  throw GaudiException("Keyed Container cannot satisfy request - severe problem!",
+                       "KeyedContainer",
+                       0);
+}
-- 
GitLab


From a501ed844358c02af6cce8684c7cdcc2347977bc Mon Sep 17 00:00:00 2001
From: Marco Clemencic <marco.clemencic@cern.ch>
Date: Thu, 19 Nov 2015 13:19:09 +0100
Subject: [PATCH 02/10] restored Containers::HashMap as template argument of
 KeyedContainer

---
 .../src/DataSvc/StoreExplorerAlg.cpp          |  7 +++---
 GaudiKernel/GaudiKernel/KeyedContainer.h      | 19 +++-------------
 GaudiKernel/GaudiKernel/KeyedTraits.h         | 22 +++++++++++++------
 3 files changed, 21 insertions(+), 27 deletions(-)

diff --git a/GaudiCommonSvc/src/DataSvc/StoreExplorerAlg.cpp b/GaudiCommonSvc/src/DataSvc/StoreExplorerAlg.cpp
index 26e190f759..ebb521611b 100644
--- a/GaudiCommonSvc/src/DataSvc/StoreExplorerAlg.cpp
+++ b/GaudiCommonSvc/src/DataSvc/StoreExplorerAlg.cpp
@@ -120,7 +120,6 @@ public:
         const CLID id = p->clID();
         log << " [" << numObj << "]";
         if ( m_testAccess )  {
-          using ko_t = KeyedObject<int>;
           CLID idd = id>>16;
           switch(idd) {
             case CLID_ObjectList>>16:                /* ObjectList    */
@@ -130,13 +129,13 @@ public:
               access((ObjectVector<ContainedObject>*)base);
               break;
             case (CLID_ObjectVector+0x00030000)>>16: /* Keyed Map     */
-              access((KeyedContainer<ko_t,std::map<ko_t::key_type, ko_t*>>*)base);
+              access((KeyedContainer<KeyedObject<int>,Containers::Map>*)base);
               break;
             case (CLID_ObjectVector+0x00040000)>>16: /* Keyed Hashmap */
-              access((KeyedContainer<ko_t,std::unordered_map<ko_t::key_type, ko_t*>>*)base);
+              access((KeyedContainer<KeyedObject<int>,Containers::HashMap>*)base);
               break;
             //case (CLID_ObjectVector+0x00050000)>>16: /* Keyed array   */
-            //  access((KeyedContainer<ko_t,Containers::Array>*)base);
+            //  access((KeyedContainer<KeyedObject<int>,Containers::Array>*)base);
             //  break;
           }
         }
diff --git a/GaudiKernel/GaudiKernel/KeyedContainer.h b/GaudiKernel/GaudiKernel/KeyedContainer.h
index 5d3f831855..1e9d0575e6 100644
--- a/GaudiKernel/GaudiKernel/KeyedContainer.h
+++ b/GaudiKernel/GaudiKernel/KeyedContainer.h
@@ -22,19 +22,6 @@
 #define FORCE_INLINE inline
 #endif
 
-template<typename T>
-struct CLID_KC_Vector_Offset {};
-
-template <class K, class V>
-struct CLID_KC_Vector_Offset<std::map<K,V>> {
-  constexpr static const CLID value = 0x00030000 + CLID_ObjectVector;
-};
-
-template <class K, class V>
-struct CLID_KC_Vector_Offset<std::unordered_map<K,V>> {
-  constexpr static const CLID value = 0x00040000 + CLID_ObjectVector;
-};
-
 /** template class KeyedContainer, KeyedContainer.h
  *
  *  This class represents a container, where the contained objects
@@ -71,14 +58,14 @@ struct CLID_KC_Vector_Offset<std::unordered_map<K,V>> {
  *  @version  1.0
  *
  */
-template <class DATATYPE, class MAPPING=std::unordered_map<typename DATATYPE::key_type, DATATYPE*>>
+template <class DATATYPE, class MAPPING=Containers::HashMap>
 class GAUDI_API KeyedContainer: public ObjectContainerBase
 {
 public:
   /// Definition of the contained object type
   typedef DATATYPE                                  contained_type;
   /// Definition of the implementing container type
-  typedef MAPPING                                   map_type;
+  typedef typename MAPPING:: template map_type<DATATYPE>  map_type;
 
   /** General container specific type definitions.
       The following type definitions are generic to most STL containers
@@ -173,7 +160,7 @@ public:
   virtual const CLID& clID() const      {              return this->classID(); }
   /// Retrieve class ID
   static const CLID& classID() {
-    static CLID cid= DATATYPE::classID() + CLID_KC_Vector_Offset<MAPPING>::value;
+    static CLID cid= DATATYPE::classID() + MAPPING::clid_offset;
     return cid;
   }
   //@}
diff --git a/GaudiKernel/GaudiKernel/KeyedTraits.h b/GaudiKernel/GaudiKernel/KeyedTraits.h
index 15fb5f33d8..b8c125e62a 100644
--- a/GaudiKernel/GaudiKernel/KeyedTraits.h
+++ b/GaudiKernel/GaudiKernel/KeyedTraits.h
@@ -5,6 +5,9 @@
 
 // Include files
 #include <vector>
+#include <map>
+#include <unordered_map>
+#include "GaudiKernel/ClassID.h"
 
 // Forward declarations
 template <class K>          class KeyedObject;
@@ -24,13 +27,6 @@ namespace Containers    {
     OBJ_CANNOT_INSERT /**< Cannot insert object into container.              */
   };
 
-  // Forward declarations
-
-  /// Container traits class
-  template <class DATATYPE>  struct traits;
-  /// Key traits class
-  template <class KEY>       struct key_traits;
-
   /** Function to be called to indicate that an object cannot be inserted
       to the container. Internally an exception is thrown.                    */
   GAUDI_API void cannotInsertToContainer();
@@ -113,6 +109,18 @@ namespace Containers    {
 #endif
     }
   };
+
+  struct Map {
+    template <class DATATYPE>
+    using map_type = std::map<typename DATATYPE::key_type, DATATYPE*>;
+    constexpr static const CLID clid_offset = 0x00030000 + CLID_ObjectVector;
+  };
+  struct HashMap{
+    template <class DATATYPE>
+    using map_type = std::unordered_map<typename DATATYPE::key_type, DATATYPE*>;
+    constexpr static const CLID clid_offset = 0x00040000 + CLID_ObjectVector;
+  };
+
 }
 #endif  // GAUDIKERNEL_KEYEDTRAITS_H
 
-- 
GitLab


From 5ca63b51a41867614643abb10e3e5d9c494d94d4 Mon Sep 17 00:00:00 2001
From: Marco Clemencic <marco.clemencic@cern.ch>
Date: Thu, 19 Nov 2015 13:46:22 +0100
Subject: [PATCH 03/10] removed some useless code

---
 GaudiKernel/GaudiKernel/KeyedContainer.h | 10 ++++-----
 GaudiKernel/GaudiKernel/KeyedTraits.h    | 28 +-----------------------
 2 files changed, 6 insertions(+), 32 deletions(-)

diff --git a/GaudiKernel/GaudiKernel/KeyedContainer.h b/GaudiKernel/GaudiKernel/KeyedContainer.h
index 1e9d0575e6..4f8af93033 100644
--- a/GaudiKernel/GaudiKernel/KeyedContainer.h
+++ b/GaudiKernel/GaudiKernel/KeyedContainer.h
@@ -113,13 +113,13 @@ private:
 
   /// Internal function to access objects within the container
   value_type i_object(const key_type& k) const  {
-    auto it = m_random.find(traits::hash(k));
+    auto it = m_random.find(k);
     return it == m_random.end() ? nullptr : it->second;
   }
 
   /// Internal function to erase an object from the container
   long i_erase(const key_type& k, const_reference v=nullptr) {
-    auto kv = m_random.find(traits::hash(k));
+    auto kv = m_random.find(k);
     if (kv != m_random.end() && (v && kv->second == v)) {
       auto it = std::find(m_sequential.begin(), m_sequential.end(), kv->second);
       m_sequential.erase(it);
@@ -463,7 +463,7 @@ StatusCode KeyedContainer<DATATYPE, MAPPING>::update()
   m_keySeq = -1;
   for(auto obj: m_sequential) {
     const auto k = obj->key();
-    m_random.insert({traits::hash(k), obj});
+    m_random.insert({k, obj});
     if (m_keySeq < k) m_keySeq = k;
   }
   return StatusCode::SUCCESS;
@@ -488,11 +488,11 @@ KeyedContainer<DATATYPE, MAPPING>::insert(const value_type val,
   if (val && ((!val->hasKey()) || (val->key() == k))) {
     // to attempt an insertion, we need an object either
     // without key or with the same key we pass
-    auto it = m_random.find(traits::hash(k));
+    auto it = m_random.find(k);
     if (it == m_random.end()) {
       traits::setKey(val, k);
       m_keySeq = std::max(k, m_keySeq);
-      m_random.insert({traits::hash(k), val});
+      m_random.insert({k, val});
       m_sequential.push_back(val);
       val->setParent(this);
       traits::addRef(val);
diff --git a/GaudiKernel/GaudiKernel/KeyedTraits.h b/GaudiKernel/GaudiKernel/KeyedTraits.h
index b8c125e62a..a01b09c86f 100644
--- a/GaudiKernel/GaudiKernel/KeyedTraits.h
+++ b/GaudiKernel/GaudiKernel/KeyedTraits.h
@@ -1,8 +1,6 @@
 #ifndef GAUDIKERNEL_KEYEDTRAITS_H
 #define GAUDIKERNEL_KEYEDTRAITS_H
 
-#define CHECK_KEYED_CONTAINER
-
 // Include files
 #include <vector>
 #include <map>
@@ -67,21 +65,8 @@ namespace Containers    {
     static key_type makeKey(int k)                     {return key_type(k); }
     /// Full unhashed key identifier
     static long identifier(const key_type& k)          {return k;           }
-    /// Hash function for this key
-    static long hash(const key_type& key_value)        {return key_value;   }
     /// Set object key when inserted into the container
     static void setKey(obj_type* v, const key_type& k) {if(v)v->setKey(k);  }
-    /** Check the validity of the object's key.
-      Select if key-checks should be performed by
-      switching on/off the macro CHECK_KEYED_CONTAINER.
-    */
-    static bool checkKey(obj_type* v,const key_type& k) {
-#ifdef CHECK_KEYED_CONTAINER
-      return (v) ? (hash(v->key())==hash(k)) : false;
-#else
-      return true;
-#endif
-    }
     /// Add reference counter to object when inserted into the container
     static long addRef(obj_type* v)      {   return (v) ? v->addRef()  : 0; }
     /// Release reference to object
@@ -97,18 +82,7 @@ namespace Containers    {
       @version  1.0
   */
   template < class DATATYPE >
-  struct traits : public key_traits < typename DATATYPE::key_type >
-  {
-    /// Allow to check the access to container elements for consistency
-    static bool checkBounds(const std::vector<DATATYPE*>* cnt,
-                            const typename DATATYPE::key_type& k) {
-#ifdef CHECK_KEYED_CONTAINER
-      return size_t(cnt->size()) > size_t(traits::hash(k));
-#else
-      return true;
-#endif
-    }
-  };
+  using traits = key_traits<typename DATATYPE::key_type>;
 
   struct Map {
     template <class DATATYPE>
-- 
GitLab


From b2437eb54ed4b5b6c026310d859fef1e6bfafe75 Mon Sep 17 00:00:00 2001
From: Marco Clemencic <marco.clemencic@cern.ch>
Date: Thu, 19 Nov 2015 19:17:53 +0100
Subject: [PATCH 04/10] restored KeyedObjectManager<hashmap> for compatibility
 with old files

---
 GaudiKernel/GaudiKernel/KeyedTraits.h | 19 +++++++++++--------
 1 file changed, 11 insertions(+), 8 deletions(-)

diff --git a/GaudiKernel/GaudiKernel/KeyedTraits.h b/GaudiKernel/GaudiKernel/KeyedTraits.h
index a01b09c86f..be76934fa7 100644
--- a/GaudiKernel/GaudiKernel/KeyedTraits.h
+++ b/GaudiKernel/GaudiKernel/KeyedTraits.h
@@ -74,27 +74,30 @@ namespace Containers    {
   };
 
   /** Definition of the container traits class.
-
-      Select if container-checks should be performed by
-      switching on/off the macro CHECK_KEYED_CONTAINER.
-
-      @author   M.Frank CERN/LHCb
-      @version  1.0
   */
   template < class DATATYPE >
   using traits = key_traits<typename DATATYPE::key_type>;
 
-  struct Map {
+  // There is no technical reason to use the dummy KeyedObjectManager<T> typedefs,
+  // instead the underlying map and hashmap classes, but we keep it for backward
+  // compatibility with old data (on file).
+  struct map {
     template <class DATATYPE>
     using map_type = std::map<typename DATATYPE::key_type, DATATYPE*>;
     constexpr static const CLID clid_offset = 0x00030000 + CLID_ObjectVector;
   };
-  struct HashMap{
+  struct hashmap{
     template <class DATATYPE>
     using map_type = std::unordered_map<typename DATATYPE::key_type, DATATYPE*>;
     constexpr static const CLID clid_offset = 0x00040000 + CLID_ObjectVector;
   };
 
+  template <typename T>
+  struct KeyedObjectManager: public T {};
+
+  typedef KeyedObjectManager<map> Map;
+  typedef KeyedObjectManager<hashmap> HashMap;
+
 }
 #endif  // GAUDIKERNEL_KEYEDTRAITS_H
 
-- 
GitLab


From 047b4cab2e70f53353e84692661a28a9b200fadf Mon Sep 17 00:00:00 2001
From: Marco Clemencic <marco.clemencic@cern.ch>
Date: Thu, 19 Nov 2015 19:19:05 +0100
Subject: [PATCH 05/10] fixed some clang warnings and clean up

---
 GaudiKernel/GaudiKernel/KeyedContainer.h | 34 ++++++------------------
 1 file changed, 8 insertions(+), 26 deletions(-)

diff --git a/GaudiKernel/GaudiKernel/KeyedContainer.h b/GaudiKernel/GaudiKernel/KeyedContainer.h
index 4f8af93033..1eb3df14d4 100644
--- a/GaudiKernel/GaudiKernel/KeyedContainer.h
+++ b/GaudiKernel/GaudiKernel/KeyedContainer.h
@@ -13,15 +13,6 @@
 #include "GaudiKernel/KeyedObject.h"
 #include "GaudiKernel/GaudiException.h"
 
-// Forward declarations
-// template <class T, class M> class KeyedContainer;
-
-#ifdef WIN32
-#define FORCE_INLINE __forceinline
-#else
-#define FORCE_INLINE inline
-#endif
-
 /** template class KeyedContainer, KeyedContainer.h
  *
  *  This class represents a container, where the contained objects
@@ -148,7 +139,7 @@ public:
   }
   KeyedContainer(const KeyedContainer&) = delete;
   /// Destructor
-  virtual ~KeyedContainer();
+  ~KeyedContainer() noexcept override { clear(); }
   //@}
 
   /**@name DataObject virtual function overloads.
@@ -157,7 +148,7 @@ public:
    */
   //@{
   /// Retrieve class ID
-  virtual const CLID& clID() const      {              return this->classID(); }
+  const CLID& clID() const override { return this->classID(); }
   /// Retrieve class ID
   static const CLID& classID() {
     static CLID cid= DATATYPE::classID() + MAPPING::clid_offset;
@@ -182,7 +173,7 @@ public:
    */
   //@{
   /// ObjectContainerBase overload: Number of objects in the container
-  virtual size_type numberOfObjects() const   {  return m_sequential.size();       }
+  size_type numberOfObjects() const override { return m_sequential.size(); }
   /** ObjectContainerBase overload: Add an object to the container.
    *  Plese see the documentation of the member function
    *
@@ -194,7 +185,7 @@ public:
    *                     container.
    *  @return            long integer representation of the key value.
    */
-  virtual long add(ContainedObject* pObject);
+  long add(ContainedObject* pObject) override;
 
   /** ObjectContainerBase overload: Remove an object from the container.
    *  Because this function is also called from the destructor of
@@ -208,18 +199,18 @@ public:
    *  @param   pObject   Pointer to the object to be removed from the
    *                     container.
    */
-  virtual long remove(ContainedObject* pObject);
+  long remove(ContainedObject* pObject) override;
 
   /** ObjectContainerBase overload: Retrieve the object by reference
    *  given the long integer representation of the object's key.
    */
-  virtual ContainedObject* containedObject(long key_value) const  {
+  ContainedObject* containedObject(long key_value) const override {
     return i_object( traits::makeKey( key_value ) );
   }
   /** ObjectContainerBase overload: Retrieve the full long integer
    *  representation of the object's key from the object base class pointer.
    */
-  virtual long index(const ContainedObject* p) const;
+  long index(const ContainedObject* p) const override;
   /** Retrieve the full content of the object container.
    *  @param   v          Vector of contained objects, which will host
    *                      all objects contained in this container.
@@ -251,7 +242,7 @@ public:
    *  This function reuses the "update" callback of the generic DataObject
    *  base class.
    */
-  virtual StatusCode update();
+  StatusCode update() override;
   //@}
 
   /**@name Sequential array access to objects using iterators.
@@ -449,13 +440,6 @@ public:
   *
   */
 
-// Destructor
-template <class DATATYPE, class MAPPING> inline
-KeyedContainer<DATATYPE, MAPPING>::~KeyedContainer()
-{
-  clear();
-}
-
 // Configure direct access
 template <class DATATYPE, class MAPPING> inline
 StatusCode KeyedContainer<DATATYPE, MAPPING>::update()
@@ -566,6 +550,4 @@ KeyedContainer<DATATYPE, MAPPING>::erase(iterator start_pos,
   m_sequential.erase(start_pos, stop_pos);
 }
 
-
-#undef FORCE_INLINE
 #endif // GAUDIKERNEL_KEYEDCONTAINER_H
-- 
GitLab


From e7cbb5d9e64b5438e2e1b1e03902b466adc8604d Mon Sep 17 00:00:00 2001
From: Marco Clemencic <marco.clemencic@cern.ch>
Date: Thu, 19 Nov 2015 19:20:09 +0100
Subject: [PATCH 06/10] fixed automatic key value in KeyedContainer for LHCb
 classes

---
 GaudiKernel/GaudiKernel/KeyedContainer.h | 12 +++++++-----
 1 file changed, 7 insertions(+), 5 deletions(-)

diff --git a/GaudiKernel/GaudiKernel/KeyedContainer.h b/GaudiKernel/GaudiKernel/KeyedContainer.h
index 1eb3df14d4..37a508dcf3 100644
--- a/GaudiKernel/GaudiKernel/KeyedContainer.h
+++ b/GaudiKernel/GaudiKernel/KeyedContainer.h
@@ -100,7 +100,7 @@ private:
   map_type       m_random;
 
   /// Keep track of the highest inserted key (for sparse containers)
-  key_type       m_keySeq{-1};
+  std::size_t    m_keySeq{std::numeric_limits<std::size_t>::max()};
 
   /// Internal function to access objects within the container
   value_type i_object(const key_type& k) const  {
@@ -444,11 +444,12 @@ public:
 template <class DATATYPE, class MAPPING> inline
 StatusCode KeyedContainer<DATATYPE, MAPPING>::update()
 {
-  m_keySeq = -1;
+  m_keySeq = std::numeric_limits<std::size_t>::max();
   for(auto obj: m_sequential) {
     const auto k = obj->key();
     m_random.insert({k, obj});
-    if (m_keySeq < k) m_keySeq = k;
+    const auto k1 = std::hash<key_type>()(k);
+    if (m_keySeq < k1) m_keySeq = k1;
   }
   return StatusCode::SUCCESS;
 }
@@ -475,11 +476,12 @@ KeyedContainer<DATATYPE, MAPPING>::insert(const value_type val,
     auto it = m_random.find(k);
     if (it == m_random.end()) {
       traits::setKey(val, k);
-      m_keySeq = std::max(k, m_keySeq);
       m_random.insert({k, val});
       m_sequential.push_back(val);
       val->setParent(this);
       traits::addRef(val);
+      const auto k1 = std::hash<key_type>()(k);
+      m_keySeq = std::max(k1, m_keySeq);
       return k;
     }
   }
@@ -495,7 +497,7 @@ KeyedContainer<DATATYPE, MAPPING>::insert(const value_type val)
 {
   if (val) {
     return val->hasKey() ? insert(val, val->key())
-                         : insert(val, ++m_keySeq);
+                         : insert(val, key_type(++m_keySeq));
   }
   // Cannot insert object...indicate bad object insertion...
   Containers::cannotInsertToContainer();
-- 
GitLab


From 594cc96cb98d0e9025a6884ae582634a27828010 Mon Sep 17 00:00:00 2001
From: Marco Clemencic <marco.clemencic@cern.ch>
Date: Thu, 19 Nov 2015 23:53:14 +0100
Subject: [PATCH 07/10] removed last reference to Containers::Array/Vector
 (never used in LHCb)

---
 GaudiCommonSvc/src/DataSvc/StoreExplorerAlg.cpp | 3 ---
 GaudiKernel/dict/dictionary.xml                 | 2 --
 2 files changed, 5 deletions(-)

diff --git a/GaudiCommonSvc/src/DataSvc/StoreExplorerAlg.cpp b/GaudiCommonSvc/src/DataSvc/StoreExplorerAlg.cpp
index ebb521611b..f0f199ea4c 100644
--- a/GaudiCommonSvc/src/DataSvc/StoreExplorerAlg.cpp
+++ b/GaudiCommonSvc/src/DataSvc/StoreExplorerAlg.cpp
@@ -134,9 +134,6 @@ public:
             case (CLID_ObjectVector+0x00040000)>>16: /* Keyed Hashmap */
               access((KeyedContainer<KeyedObject<int>,Containers::HashMap>*)base);
               break;
-            //case (CLID_ObjectVector+0x00050000)>>16: /* Keyed array   */
-            //  access((KeyedContainer<KeyedObject<int>,Containers::Array>*)base);
-            //  break;
           }
         }
       }
diff --git a/GaudiKernel/dict/dictionary.xml b/GaudiKernel/dict/dictionary.xml
index c004c6b87a..3ba3a7abee 100644
--- a/GaudiKernel/dict/dictionary.xml
+++ b/GaudiKernel/dict/dictionary.xml
@@ -217,8 +217,6 @@
 
   <class name="Containers::KeyedObjectManager<Containers::hashmap>"/>
   <class name="Containers::KeyedObjectManager<Containers::map>"/>
-  <class name="Containers::KeyedObjectManager<Containers::array>"/>
-  <class name="Containers::KeyedObjectManager<Containers::vector>"/>
 
   <!--class name="std::vector<std::basic_string<char> >"/-->
 
-- 
GitLab


From e31de0ee6d1373fb59b29d496cdade7ac58efbc8 Mon Sep 17 00:00:00 2001
From: Marco Clemencic <marco.clemencic@cern.ch>
Date: Fri, 20 Nov 2015 00:54:03 +0100
Subject: [PATCH 08/10] attempt to avoid the need of hashable keys in
 KeyedContainer

---
 GaudiKernel/GaudiKernel/KeyedContainer.h | 25 ++++++++++++------------
 GaudiKernel/GaudiKernel/KeyedTraits.h    |  4 ++--
 2 files changed, 15 insertions(+), 14 deletions(-)

diff --git a/GaudiKernel/GaudiKernel/KeyedContainer.h b/GaudiKernel/GaudiKernel/KeyedContainer.h
index 37a508dcf3..b3d86fe896 100644
--- a/GaudiKernel/GaudiKernel/KeyedContainer.h
+++ b/GaudiKernel/GaudiKernel/KeyedContainer.h
@@ -100,17 +100,20 @@ private:
   map_type       m_random;
 
   /// Keep track of the highest inserted key (for sparse containers)
-  std::size_t    m_keySeq{std::numeric_limits<std::size_t>::max()};
+  typedef typename map_type::key_type map_key_type;
+  map_key_type   m_keySeq{-1};
+
+  inline static map_key_type to_map_key(const key_type& k) { return k; }
 
   /// Internal function to access objects within the container
   value_type i_object(const key_type& k) const  {
-    auto it = m_random.find(k);
+    auto it = m_random.find(to_map_key(k));
     return it == m_random.end() ? nullptr : it->second;
   }
 
   /// Internal function to erase an object from the container
   long i_erase(const key_type& k, const_reference v=nullptr) {
-    auto kv = m_random.find(k);
+    auto kv = m_random.find(to_map_key(k));
     if (kv != m_random.end() && (v && kv->second == v)) {
       auto it = std::find(m_sequential.begin(), m_sequential.end(), kv->second);
       m_sequential.erase(it);
@@ -121,7 +124,6 @@ private:
     }
     return static_cast<long>(Containers::OBJ_NOT_FOUND);
   }
-
   //@}
 
 public:
@@ -444,12 +446,11 @@ public:
 template <class DATATYPE, class MAPPING> inline
 StatusCode KeyedContainer<DATATYPE, MAPPING>::update()
 {
-  m_keySeq = std::numeric_limits<std::size_t>::max();
+  m_keySeq = -1;
   for(auto obj: m_sequential) {
-    const auto k = obj->key();
+    const auto k = to_map_key(obj->key());
     m_random.insert({k, obj});
-    const auto k1 = std::hash<key_type>()(k);
-    if (m_keySeq < k1) m_keySeq = k1;
+    if (m_keySeq < k) m_keySeq = k;
   }
   return StatusCode::SUCCESS;
 }
@@ -473,14 +474,14 @@ KeyedContainer<DATATYPE, MAPPING>::insert(const value_type val,
   if (val && ((!val->hasKey()) || (val->key() == k))) {
     // to attempt an insertion, we need an object either
     // without key or with the same key we pass
-    auto it = m_random.find(k);
+    const auto k1 = to_map_key(k);
+    auto it = m_random.find(k1);
     if (it == m_random.end()) {
       traits::setKey(val, k);
-      m_random.insert({k, val});
+      m_random.insert({k1, val});
       m_sequential.push_back(val);
       val->setParent(this);
       traits::addRef(val);
-      const auto k1 = std::hash<key_type>()(k);
       m_keySeq = std::max(k1, m_keySeq);
       return k;
     }
@@ -545,7 +546,7 @@ KeyedContainer<DATATYPE, MAPPING>::erase(iterator start_pos,
 {
   std::for_each(start_pos, stop_pos,
     [this](value_type &v) {
-      m_random.erase(v->key());
+      m_random.erase(to_map_key(v->key()));
       if (v->parent() == this) v->setParent(nullptr);
       traits::release(v);
   });
diff --git a/GaudiKernel/GaudiKernel/KeyedTraits.h b/GaudiKernel/GaudiKernel/KeyedTraits.h
index be76934fa7..c41e44ff8b 100644
--- a/GaudiKernel/GaudiKernel/KeyedTraits.h
+++ b/GaudiKernel/GaudiKernel/KeyedTraits.h
@@ -83,12 +83,12 @@ namespace Containers    {
   // compatibility with old data (on file).
   struct map {
     template <class DATATYPE>
-    using map_type = std::map<typename DATATYPE::key_type, DATATYPE*>;
+    using map_type = std::map<long, DATATYPE*>;
     constexpr static const CLID clid_offset = 0x00030000 + CLID_ObjectVector;
   };
   struct hashmap{
     template <class DATATYPE>
-    using map_type = std::unordered_map<typename DATATYPE::key_type, DATATYPE*>;
+    using map_type = std::unordered_map<long, DATATYPE*>;
     constexpr static const CLID clid_offset = 0x00040000 + CLID_ObjectVector;
   };
 
-- 
GitLab


From b2bf64c234294d1bc74da8b9c036546c33a3110e Mon Sep 17 00:00:00 2001
From: Marco Clemencic <marco.clemencic@cern.ch>
Date: Fri, 20 Nov 2015 01:09:49 +0100
Subject: [PATCH 09/10] allow key conversion to long via hash function or
 implicit conversion

---
 GaudiKernel/GaudiKernel/KeyedContainer.h | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/GaudiKernel/GaudiKernel/KeyedContainer.h b/GaudiKernel/GaudiKernel/KeyedContainer.h
index b3d86fe896..b59229573a 100644
--- a/GaudiKernel/GaudiKernel/KeyedContainer.h
+++ b/GaudiKernel/GaudiKernel/KeyedContainer.h
@@ -103,7 +103,11 @@ private:
   typedef typename map_type::key_type map_key_type;
   map_key_type   m_keySeq{-1};
 
-  inline static map_key_type to_map_key(const key_type& k) { return k; }
+  // if the key provides a hash method we use it, otherwise we fall back
+  // on implicit conversion to map_key_type.
+  template <typename K, typename=decltype(K().hash())>
+  inline static map_key_type to_map_key(const K& k) { return k.hash(); }
+  inline static map_key_type to_map_key(map_key_type k) { return k; }
 
   /// Internal function to access objects within the container
   value_type i_object(const key_type& k) const  {
-- 
GitLab


From df14e2389f9dbc7ae12868587eab72d0c3e2465e Mon Sep 17 00:00:00 2001
From: Marco Clemencic <marco.clemencic@cern.ch>
Date: Fri, 20 Nov 2015 07:50:18 +0100
Subject: [PATCH 10/10] minor optimization in KeyedContainer::clear

---
 GaudiKernel/GaudiKernel/KeyedContainer.h | 14 +++++++++++++-
 1 file changed, 13 insertions(+), 1 deletion(-)

diff --git a/GaudiKernel/GaudiKernel/KeyedContainer.h b/GaudiKernel/GaudiKernel/KeyedContainer.h
index b59229573a..96665b3d61 100644
--- a/GaudiKernel/GaudiKernel/KeyedContainer.h
+++ b/GaudiKernel/GaudiKernel/KeyedContainer.h
@@ -237,7 +237,7 @@ public:
   /// Reserve place for "value" objects in the container.
   void reserve(size_type value)         {      m_sequential.reserve(value);   }
   /// Clear the entire content and erase the objects from the container
-  void clear()                          {      erase(begin(), end());         }
+  void clear();
   /** Retrieve the full content of the object container by reference.
    *  Returned is the random access container if in sequntial direct
    *  access mode. Otherwise the sequential access container is returned
@@ -543,6 +543,18 @@ long KeyedContainer<DATATYPE, MAPPING>::remove(ContainedObject* p)
   return p1 ? this->erase(p1) : (long) Containers::OBJ_NOT_FOUND;
 }
 
+template <class DATATYPE, class MAPPING> inline
+void
+KeyedContainer<DATATYPE, MAPPING>::clear()
+{
+  for(auto v: m_sequential) {
+    if (v->parent() == this) v->setParent(nullptr);
+    traits::release(v);
+  }
+  m_sequential.clear();
+  m_random.clear();
+}
+
 template <class DATATYPE, class MAPPING> inline
 void
 KeyedContainer<DATATYPE, MAPPING>::erase(iterator start_pos,
-- 
GitLab