/*========================================================================= * * Copyright NumFOCUS * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0.txt * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *=========================================================================*/ #ifndef itkMapContainer_h #define itkMapContainer_h #include "itkObject.h" #include "itkObjectFactory.h" #include namespace itk { /** \class MapContainer * \brief A wrapper of the STL "map" container. * * Define a front-end to the STL "map" container that conforms to the * IndexedContainerInterface. This is a full-fledged Object, so * there are events, modification time, debug, and reference count * information. * * \tparam TElementIdentifier A type that shall be used to index the * container. It must have a < operator defined for ordering. * * \tparam TElement The element type stored in the container. * * \ingroup DataRepresentation * \ingroup ITKCommon */ template class ITK_TEMPLATE_EXPORT MapContainer : public Object , private std::map { public: ITK_DISALLOW_COPY_AND_MOVE(MapContainer); /** Standard class type aliases. */ using Self = MapContainer; using Superclass = Object; using Pointer = SmartPointer; using ConstPointer = SmartPointer; /** \see LightObject::GetNameOfClass() */ itkOverrideGetNameOfClassMacro(MapContainer); /** Save the template parameters. */ using ElementIdentifier = TElementIdentifier; using Element = TElement; private: /** Quick access to the STL map type that was inherited. */ using MapType = std::map; using MapIterator = typename MapType::iterator; using MapConstIterator = typename MapType::const_iterator; using MapKeyCompareType = typename MapType::key_compare; public: /** Provide pass-through constructors corresponding to all the STL * map constructors. These are for internal use only since this is also * an Object which must be constructed through the "New()" routine. */ MapContainer() : MapType() {} MapContainer(const MapKeyCompareType & comp) : MapType(comp) {} // MapContainer(const Self& r):MapType(r) {} template MapContainer(TInputIterator first, TInputIterator last) : MapType(first, last) {} template MapContainer(TInputIterator first, TInputIterator last, const MapKeyCompareType & comp) : MapType(first, last, comp) {} /** Method for creation through the object factory. */ itkNewMacro(Self); /** This type is provided to adapt this container as an STL container */ using STLContainerType = MapType; /** Cast the container to a STL container type */ STLContainerType & CastToSTLContainer() noexcept { return *this; } /** Cast the container to a const STL container type */ const STLContainerType & CastToSTLConstContainer() const noexcept { return *this; } using STLContainerType::begin; using STLContainerType::cbegin; using STLContainerType::end; using STLContainerType::cend; using STLContainerType::rbegin; using STLContainerType::crbegin; using STLContainerType::rend; using STLContainerType::crend; using STLContainerType::empty; using STLContainerType::size; using STLContainerType::max_size; using STLContainerType::operator[]; using STLContainerType::insert; using STLContainerType::erase; using STLContainerType::swap; using STLContainerType::clear; using STLContainerType::key_comp; using STLContainerType::value_comp; using STLContainerType::find; using STLContainerType::count; using STLContainerType::lower_bound; using STLContainerType::upper_bound; using STLContainerType::equal_range; using STLContainerType::get_allocator; using typename STLContainerType::key_type; using typename STLContainerType::mapped_type; using typename STLContainerType::value_type; using typename STLContainerType::key_compare; using typename STLContainerType::value_compare; using typename STLContainerType::allocator_type; using typename STLContainerType::reference; using typename STLContainerType::const_reference; using typename STLContainerType::iterator; using typename STLContainerType::const_iterator; using typename STLContainerType::size_type; using typename STLContainerType::difference_type; using typename STLContainerType::pointer; using typename STLContainerType::const_pointer; using typename STLContainerType::reverse_iterator; using typename STLContainerType::const_reverse_iterator; /** Declare iterators to container. */ class Iterator; class ConstIterator; friend class Iterator; friend class ConstIterator; /** \class Iterator * \brief The non-const iterator type for the map. * \ingroup ITKCommon */ class Iterator { public: using iterator_category = typename MapIterator::iterator_category; using value_type = typename MapIterator::value_type; using difference_type = typename MapIterator::difference_type; using pointer = typename MapIterator::pointer; using reference = typename MapIterator::reference; Iterator() = default; Iterator(const MapIterator & i) : m_Iter(i) {} Iterator & operator*() { return *this; } Iterator * operator->() { return this; } Iterator & operator++() { ++m_Iter; return *this; } Iterator operator++(int) { Iterator temp(*this); ++m_Iter; return temp; } Iterator & operator--() { --m_Iter; return *this; } Iterator operator--(int) { Iterator temp(*this); --m_Iter; return temp; } bool operator==(const Iterator & r) const { return m_Iter == r.m_Iter; } ITK_UNEQUAL_OPERATOR_MEMBER_FUNCTION(Iterator); bool operator==(const ConstIterator & r) const { return m_Iter == r.m_Iter; } ITK_UNEQUAL_OPERATOR_MEMBER_FUNCTION(ConstIterator); /** Get the index into the MapContainer associated with this iterator. */ ElementIdentifier Index() const { return m_Iter->first; } /** Get the value at this iterator's location in the MapContainer. */ Element & Value() { return m_Iter->second; } private: MapIterator m_Iter; friend class ConstIterator; }; /** \class ConstIterator * \brief The const iterator type for the map. * \ingroup ITKCommon */ class ConstIterator { public: using iterator_category = typename MapConstIterator::iterator_category; using value_type = typename MapConstIterator::value_type; using difference_type = typename MapConstIterator::difference_type; using pointer = typename MapConstIterator::pointer; using reference = typename MapConstIterator::reference; ConstIterator() = default; ConstIterator(const MapConstIterator & ci) : m_Iter(ci) {} ConstIterator(const Iterator & r) : m_Iter(r.m_Iter) {} ConstIterator & operator*() { return *this; } ConstIterator * operator->() { return this; } ConstIterator & operator++() { ++m_Iter; return *this; } ConstIterator operator++(int) { ConstIterator temp(*this); ++m_Iter; return temp; } ConstIterator & operator--() { --m_Iter; return *this; } ConstIterator operator--(int) { ConstIterator temp(*this); --m_Iter; return temp; } bool operator==(const Iterator & r) const { return m_Iter == r.m_Iter; } ITK_UNEQUAL_OPERATOR_MEMBER_FUNCTION(Iterator); bool operator==(const ConstIterator & r) const { return m_Iter == r.m_Iter; } ITK_UNEQUAL_OPERATOR_MEMBER_FUNCTION(ConstIterator); /** Get the index into the MapContainer associated with this iterator. */ ElementIdentifier Index() const { return m_Iter->first; } /** Get the value at this iterator's location in the MapContainer. */ const Element & Value() const { return m_Iter->second; } private: MapConstIterator m_Iter; friend class Iterator; }; /* Declare the public interface routines. */ /** * Get a reference to the element at the given index. * If the index does not exist, it is created automatically. * * It is assumed that the value of the element is modified through the * reference. */ Element & ElementAt(ElementIdentifier); /** * Get a reference to the element at the given index. * */ const Element & ElementAt(ElementIdentifier) const; /** * Get a reference to the element at the given index. * If the index does not exist, it is created automatically. * * It is assumed that the value of the element is modified through the * reference. */ Element & CreateElementAt(ElementIdentifier); /** * Get the element at the specified index. There is no check for * existence performed. */ Element GetElement(ElementIdentifier) const; /** * Set the given index value to the given element. If the index doesn't * exist, it is automatically created. */ void SetElement(ElementIdentifier, Element); /** * Set the given index value to the given element. If the index doesn't * exist, it is automatically created. */ void InsertElement(ElementIdentifier, Element); /** * Check if the STL map has an entry corresponding to the given index. * The count will be either 1 or 0. */ bool IndexExists(ElementIdentifier) const; /** * If the given index doesn't exist in the map, return false. * Otherwise, set the element through the pointer (if it isn't null), and * return true. */ bool GetElementIfIndexExists(ElementIdentifier, Element *) const; /** * The map will create an entry for a given index through the indexing * operator. Whether or not it is created, it will be assigned to the * default element. */ void CreateIndex(ElementIdentifier); /** * Delete the entry in the STL map corresponding to the given identifier. * If the entry does not exist, nothing happens. */ void DeleteIndex(ElementIdentifier); /** * Get a begin const iterator for the map. */ ConstIterator Begin() const; /** * Get an end const iterator for the map. */ ConstIterator End() const; /** * Get a begin const iterator for the map. */ Iterator Begin(); /** * Get an end const iterator for the map. */ Iterator End(); /** * Get the number of elements currently stored in the map. */ ElementIdentifier Size() const; /** * Tell the container to allocate enough memory to allow at least * as many elements as the size given to be stored. This is NOT * guaranteed to actually allocate any memory, but is useful if the * implementation of the container allocates contiguous storage. */ void Reserve(ElementIdentifier); /** * Tell the container to try to minimize its memory usage for storage of * the current number of elements. This is NOT guaranteed to decrease * memory usage. */ void Squeeze(); /** * Tell the container to release any memory it may have allocated and * return itself to its initial state. */ void Initialize(); }; } // end namespace itk #ifndef ITK_MANUAL_INSTANTIATION # include "itkMapContainer.hxx" #endif #endif