2019年8月4日日曜日

8: C++スタンダード'map'互換の要素群順序維持マップ

<このシリーズの前の記事 | このシリーズの目次 | このシリーズの次の記事>

要素群順序を要素群投入順に維持するスタンダードマップはありません。ここに、'::std::map'互換のものがあります。

話題


About: C++

この記事の目次


開始コンテキスト



ターゲットコンテキスト



  • 読者は、スタンダード'map'の代わりにあらゆる可能な許されたケースで使用できる、要素群の順序が維持されるマップを入手し、そうしたマップを作成する方法を理解する。

オリエンテーション


Hypothesizer 7
要素群の順序が維持されるマップが私は欲しい。要素が、指定した位置に挿入され、それに応じて取り出されるマップが。

スタンダード'map'はそういうマップではない

私のマップは、スタンダード'map'に無関係なものであって欲しくなく、スタンダード'map'の代わりにあらゆる可能な許されたケースで使用できるマップであって欲しい(「あらゆる可能な許された」で私が何を意味しているかは、前記事で説明されている)。

私の最初の、自然な(オブジェクト指向プログラミングパラダイムにしたがえばこれが自然であると私は考える)計画は、スタンダード'map'をパブリックに拡張することであったが、スタンダード'map'は拡張されるように想定されていないと判明し、スタンダードコンテナ互換のカスタムコンテナがどのように作成されるように想定されているかを私は理解した。

今や、コンセプトは明確になったが、そうしたカスタムマップを実際に実装するのは、結構、大変である。しかし、とにかく私はそれを作成した、'本体'で見られるとおり。


本体


1: 私のスタンダード'map'互換要素群順序維持マップはどのようなものであるか?


Hypothesizer 7
「要素群の順序が維持されるマップ」で私が意味しているのは、要素が、指定した位置に挿入され、それに応じて取り出されるマップのことだ。

要素が、私の要素群順序維持マップのインスタンスに位置を明示的に指定されずに追加された場合は、その要素はそのマップインスタンスに最後尾要素として挿入される。要素が、そのマップインスタンスに位置をイテレータで明示的に指定されて挿入された場合は、その要素はその位置の前に挿入される。

そのマップインスタンスの要素群がイテレートされる時は、要素群は、それらがそのマップインスタンスに挿入された際に決定された順序で取得される。

そして、私のマップは、スタンダード'map'の代わりにあらゆる可能な許されたケース(「あらゆる可能な許された」で私が何を意味しているかは、前記事で説明されている)で使用できるものと想定される。


2: 私のスタンダード'map'互換要素群順序維持マップのラフスケッチ


Hypothesizer 7
私のマップは、スタンダード'map'の代わりにあらゆる可能な許されたケースで使用できるものと想定されているので、全てのパブリック要素(メンバーだけでなくタイプも)を実装し、それらのそれぞれが、対応するスタンダード'map'パブリック要素と同一シグネチャーを持っていなければならない、前記事で論じられたとおり。

そうしたパブリック要素群がどのようなものであるかは、このページとそのサブページ群から学んだ。

私の最初の計画は、私のマップに1つのスタンダード'map'インスタンスを持たせ、そのキータイプを私のマップのキータイプにし、そのバリュータイプをあるクラスにし、そのメンバーとして私のマップの要素の値、前キー、次キーを持たせるというものであった。以下のコードがそのコンセプトを明確にするだろう。

@C++ ソースコード
#include <map>
#include <mutex>
#include <optional>

			template <typename T, typename U, typename W = less <T>> class NavigableLinkedMap {
				public:
					typedef T key_type;
					typedef U mapped_type;
					typedef W key_compare;
				private:
					class ValueAndLinks {
						private:
						    mapped_type i_value;
							optional <key_type> i_previousKey;
							optional <key_type> i_nextKey;
						public:
							ValueAndLinks ();
							ValueAndLinks (mapped_type a_value, optional <key_type> a_previousKey, optional <key_type> a_nextKey);
							mapped_type getValue ();
							void setValue (mapped_type a_value);
							optional <key_type> getPreviousKey ();
							void setPreviousKey (optional <key_type> a_previousKey);
							optional <key_type> getNextKey ();
							void setNextKey (optional <key_type> a_nextKey);
					};
				private:
					map <key_type, ValueAndLinks, key_compare> * i_keyToValueAndLinksMap;
					optional <key_type> * i_firstKey;
					optional <key_type> * i_lastKey;
					mutex i_mutex;
			};

実のところ、その方法で、類似のマップ(ナビゲート可能で要素挿入可能なリンクトハッシュマップ)をJavaで私は作成した。

しかしながら、それには問題があることが判明した: 例えば、私のマップの非コンスタントイテレータクラスの'->'オペレーターのリターンタイプは'pair <key_type const, mapped_type> *'でなければならないが、それは容易でない、なぜなら、'*i_keyToValueAndLinksMap'は'pair <key_type const, mapped_type>'タイプのデータを持っておらず、持っているのは'pair <key_type const, ValueAndLinks>'タイプのデータだから(そのオペレーターがそういうデータ(それはヒープデータでなければならず、そのヒープデータを適切な時点で除去する仕組みが必要になるだろう)を新たに作成するというのは意味がない、なぜなら、そのオペレーターがアドレスを戻すことの要点は、そのデータへの変更が'*i_keyToValueAndLinksMap'に反映されることだから)。

そこで、私は、私のマップに2つのスタンダード'map'インスタンスを持たせ、その内の1つは、キータイプが私のマップのキータイプでバリュータイプが私のマップのバリュータイプであるスタンダード'map'インスタンス、他方は、キータイプが私のマップのキータイプでバリュータイプがメンバーに前キー、次キーを持つクラスであるスタンダード'map'インスタンスであるようにした。以下のコードがそのコンセプトを明確にするだろう。

@C++ ソースコード
#include <map>
#include <mutex>
#include <optional>

			template <typename T, typename U, typename W = less <T>> class NavigableLinkedMap {
				public:
					typedef T key_type;
					typedef U mapped_type;
					typedef W key_compare;
				private:
					class Links {
						private:
							optional <key_type> i_previousKey;
							optional <key_type> i_nextKey;
						public:
							Links ();
							Links (optional <key_type> a_previousKey, optional <key_type> a_nextKey);
							optional <key_type> getPreviousKey ();
							void setPreviousKey (optional <key_type> a_previousKey);
							optional <key_type> getNextKey ();
							void setNextKey (optional <key_type> a_nextKey);
					};
				private:
					map <key_type, mapped_type, key_compare> * i_keyToValueMap;
					map <key_type, Links, key_compare> * i_keyToLinksMap;
					optional <key_type> * i_firstKey;
					optional <key_type> * i_lastKey;
					mutex i_mutex;
			};

'i_keyToValueMap'、'i_keyToLinksMap'、'i_firstKey'、'i_lastKey'がポインターである理由は、そうすることで、私のマップの'swap'メソッドの実装が容易になるから: 'swap'メソッドは、2つのマップインスタンス間でアドレスをスワップさせるだけでよい。

いくつかのメンバー変数が'optional'であるが、それは、それらの変数がオプショナルだから: 例えば、先頭要素は前キーを持たない。

私のマップは、インスタンスを変更する一部のメソッドが複数スレッドから同時に呼ばれるのを防ぐために、そのミューテックスを持っている。


3: 全コード


Hypothesizer 7
以下が、私のスタンダード'map'互換要素群順序維持マップの全コードだ。

theBiasPlanet/coreUtilities/visualCplusplusSpecificHeaders/VisualCplusplusSpecificDefinitions.hpp

@C++ ソースコード
#ifndef __theBiasPlanet_coreUtilities_visualCplusplusSpecificHeaders_VisualCplusplusSpecificDefinitions_hpp__
#define __theBiasPlanet_coreUtilities_visualCplusplusSpecificHeaders_VisualCplusplusSpecificDefinitions_hpp__

#ifdef GCC
#define __symbolExportingDeclarationForVisualCplusplus__
#define __symbolExportingOrImportingDeclarationForVisualCplusplus__
#else
#ifdef __dllExport__
#define __symbolExportingDeclarationForVisualCplusplus__ __declspec (dllexport)
#define __symbolExportingOrImportingDeclarationForVisualCplusplus__ __declspec (dllexport)
#else
#define __symbolExportingDeclarationForVisualCplusplus__
#define __symbolExportingOrImportingDeclarationForVisualCplusplus__ __declspec (dllimport)
#endif
#endif

#endif

theBiasPlanet/coreUtilities/collections/NavigableLinkedMap.hpp

@C++ ソースコード
#ifndef __theBiasPlanet_coreUtilities_collections_NavigableLinkedMap_hpp__
#define __theBiasPlanet_coreUtilities_collections_NavigableLinkedMap_hpp__

#include <initializer_list>
#include <map>
#include <mutex>
#include <optional>
#include "theBiasPlanet/coreUtilities/visualCplusplusSpecificHeaders/VisualCplusplusSpecificDefinitions.hpp"

using namespace ::std;

namespace theBiasPlanet {
	namespace coreUtilities {
		namespace collections {
			template <typename T, typename U, typename W = less <T>> class __symbolExportingDeclarationForVisualCplusplus__ NavigableLinkedMap {
				public:
					typedef T key_type;
					typedef U mapped_type;
					typedef W key_compare;
				private:
					class Links {
						private:
							optional <key_type> i_previousKey;
							optional <key_type> i_nextKey;
						public:
							Links ();
							Links (optional <key_type> a_previousKey, optional <key_type> a_nextKey);
							optional <key_type> getPreviousKey ();
							void setPreviousKey (optional <key_type> a_previousKey);
							optional <key_type> getNextKey ();
							void setNextKey (optional <key_type> a_nextKey);
					};
				public:
					typedef pair <key_type const, mapped_type> value_type;
					class ValueComparer {
						private:
							key_compare i_keyComparer;
						public:
							ValueComparer (key_compare a_keyComparer);
							bool operator () (value_type const & a_keyValuePair1, value_type const & a_keyValuePair2) const;
					};
					typedef ValueComparer value_compare;
					typedef allocator <value_type> allocator_type;
					typedef value_type & reference;
					typedef value_type const & const_reference;
					typedef value_type * pointer;
					typedef value_type const * const_pointer;
					class BaseIterator {
						protected:
							map <key_type, mapped_type, key_compare> * i_keyToValueMap;
							map <key_type, Links, key_compare> * i_keyToLinksMap;
							optional <key_type> * i_firstKey;
							optional <key_type> * i_lastKey;
							optional <key_type> i_currentKey;
							virtual void goToNextElement ();
							virtual void goToPreviousElement ();
						public:
							typedef ptrdiff_t difference_type;
							typedef bidirectional_iterator_tag iterator_category;
							BaseIterator (NavigableLinkedMap <key_type, mapped_type, key_compare> const & a_navigableLinkedMap, optional <key_type> a_currentKey);
							BaseIterator (BaseIterator const & a_originalIterator);
							virtual bool operator == (BaseIterator const & a_iteratorToBeCompared) const;
							virtual bool operator != (BaseIterator const & a_iteratorToBeCompared) const;
					};
					class NonConstantIterator : public BaseIterator {
						public:
							typedef pair <key_type const, mapped_type> value_type;
							typedef value_type * pointer;
							typedef value_type & reference;
							NonConstantIterator (NavigableLinkedMap <key_type, mapped_type, key_compare> const & a_navigableLinkedMap, optional <key_type> a_currentKey);
							NonConstantIterator (BaseIterator const & a_originalIterator);
							virtual NonConstantIterator & operator ++ ();
							virtual NonConstantIterator operator ++ (int);
							virtual NonConstantIterator & operator -- ();
							virtual NonConstantIterator operator -- (int);
							virtual value_type & operator * ();
							virtual value_type * operator -> ();
					};
					class ConstantIterator : public BaseIterator {
						public:
							typedef pair <key_type const, mapped_type> const value_type;
							typedef pair <key_type const, mapped_type> NonConstantvalue_type;
							typedef value_type * pointer;
							typedef value_type & reference;
							ConstantIterator (NavigableLinkedMap <key_type, mapped_type, key_compare> const & a_navigableLinkedMap, optional <key_type> a_currentKey);
							ConstantIterator (BaseIterator const & a_originalIterator);
							virtual ConstantIterator & operator ++ ();
							virtual ConstantIterator operator ++ (int);
							virtual ConstantIterator & operator -- ();
							virtual ConstantIterator operator -- (int);
							virtual value_type & operator * ();
							virtual value_type * operator -> ();
					};
					typedef NonConstantIterator iterator;
					typedef ConstantIterator const_iterator;
					typedef ::std::reverse_iterator <iterator> reverse_iterator;
					typedef ::std::reverse_iterator <const_iterator> const_reverse_iterator;
					typedef ptrdiff_t difference_type;
					typedef size_t size_type;
				private:
					map <key_type, mapped_type, key_compare> * i_keyToValueMap;
					map <key_type, Links, key_compare> * i_keyToLinksMap;
					optional <key_type> * i_firstKey;
					optional <key_type> * i_lastKey;
					mutex i_mutex;
					pair <key_type &, mapped_type &> getKeyValuePair (key_type & a_key, mapped_type & a_value);
					virtual void insertNewElementAtEnd (key_type const a_key, optional <mapped_type> a_value);
					virtual void insertNewElementAtMiddle (key_type const a_positionKey, key_type const a_key, optional <mapped_type> a_value);
					virtual void updateElement (key_type const a_key, mapped_type a_value);
				public:
					explicit NavigableLinkedMap (key_compare const & a_keysComparer = key_compare ());
					template <typename V> NavigableLinkedMap (V a_iteratorPointedAtFirstElement, V a_iteratorPointedAtLastElementNotIncluded, key_compare const & a_keysComparer = key_compare ());
					NavigableLinkedMap (initializer_list <value_type> a_initializer, key_compare const & a_keysComparer = key_compare ());
					NavigableLinkedMap (NavigableLinkedMap const & a_navigableLinkedMap);
					virtual ~NavigableLinkedMap ();
					virtual NavigableLinkedMap <T, U, W> & operator = (NavigableLinkedMap <T, U, W> const & a_navigableLinkedMap);
					virtual iterator begin ();
					virtual const_iterator begin () const;
					virtual iterator end ();
					virtual const_iterator end () const;
					virtual reverse_iterator rbegin ();
					virtual const_reverse_iterator rbegin () const;
					virtual reverse_iterator rend ();
					virtual const_reverse_iterator rend () const;
					virtual const_iterator cbegin () const noexcept;
					virtual const_iterator cend () const noexcept;
					virtual const_reverse_iterator crbegin () const noexcept;
					virtual const_reverse_iterator crend () const noexcept;
					virtual bool empty () const;
					virtual size_type size () const;
					virtual size_type max_size () const;
					virtual mapped_type & operator [] (key_type const & a_key);
					virtual mapped_type & at (key_type const & a_key);
					virtual mapped_type const & at (key_type const & a_key) const;
					virtual pair <iterator, bool> insert (value_type const & a_keyValuePair);
					virtual iterator insert (iterator a_position, value_type const & a_keyValuePair);
					// Any template method cannot be virtual only because it is decided so by the specification.
					template <typename V> void insert (V a_iteratorPointedAtFirstElement, V a_iteratorPointedAtLastElementNotIncluded);
					virtual void erase (iterator a_position);
					virtual size_type erase (key_type const & a_key);
     				virtual void erase (iterator a_iteratorPointedAtFirstElement, iterator a_iteratorPointedAtLastElementNotIncluded);
					virtual void swap (NavigableLinkedMap <T, U, W> & a_navigableLinkedMap);
					virtual void clear();
					template <typename ... V> pair <iterator, bool> emplace (V && ... a_arguments);
					template <typename ... V> iterator emplace_hint (const_iterator a_position, V && ... a_arguments);
					virtual key_compare key_comp () const;
					virtual value_compare value_comp () const;
					virtual iterator find (key_type const & a_key);
					virtual const_iterator find (key_type const & a_key) const;
					virtual size_type count (key_type const & a_key) const;
					virtual iterator lower_bound (key_type const & a_key);
					virtual const_iterator lower_bound (key_type const & a_key) const;
					virtual iterator upper_bound (key_type const & a_key);
					virtual const_iterator upper_bound (key_type const & a_key) const;
					virtual pair <const_iterator, const_iterator> equal_range (key_type const & a_key) const;
					virtual pair <iterator, iterator> equal_range (key_type const & a_key);
					virtual allocator_type get_allocator () const;
			};
		}
	}
}

#endif

theBiasPlanet/coreUtilities/collections/NavigableLinkedMap.tpp

@C++ ソースコード
#include "theBiasPlanet/coreUtilities/collections/NavigableLinkedMap.hpp"
#include <cstdarg>
#include <stdexcept>
#include <string>
#include "theBiasPlanet/coreUtilities/locksHandling/Locker.hpp"

using namespace ::theBiasPlanet::coreUtilities::locksHandling;

namespace theBiasPlanet {
	namespace coreUtilities {
		namespace collections {
			template <typename T, typename U, typename W> NavigableLinkedMap <T, U, W>::Links::Links () : i_previousKey (nullopt), i_nextKey (nullopt) {
			}
			
			template <typename T, typename U, typename W> NavigableLinkedMap <T, U, W>::Links::Links (optional <key_type> a_previousKey, optional <key_type> a_nextKey) : i_previousKey (a_previousKey), i_nextKey (a_nextKey) {
			}
			
			template <typename T, typename U, typename W> optional <typename NavigableLinkedMap <T, U, W>::key_type> NavigableLinkedMap <T, U, W>::Links::getPreviousKey () {
				return i_previousKey;
			}
			
			template <typename T, typename U, typename W> void NavigableLinkedMap <T, U, W>::Links::setPreviousKey (optional <key_type> a_previousKey) {
				i_previousKey = a_previousKey;
			}
			
			template <typename T, typename U, typename W> optional <typename NavigableLinkedMap <T, U, W>::key_type> NavigableLinkedMap <T, U, W>::Links::getNextKey () {
				return i_nextKey;
			}
			
			template <typename T, typename U, typename W> void NavigableLinkedMap <T, U, W>::Links::setNextKey (optional <key_type> a_nextKey) {
				i_nextKey = a_nextKey;
			}
			
			template <typename T, typename U, typename W> pair <typename NavigableLinkedMap <T, U, W>::key_type &, typename NavigableLinkedMap <T, U, W>::mapped_type &> NavigableLinkedMap <T, U, W>::getKeyValuePair (key_type & a_key, mapped_type & a_value) {
				return pair <key_type &, mapped_type &> (a_key, a_value);
			}
			
			template <typename T, typename U, typename W> NavigableLinkedMap <T, U, W>::ValueComparer::ValueComparer (key_compare a_keyComparer) : i_keyComparer (a_keyComparer) {
			}
			
			template <typename T, typename U, typename W> bool NavigableLinkedMap <T, U, W>::ValueComparer::operator () (value_type const & a_keyValuePair1, value_type const & a_keyValuePair2) const {
				return i_keyComparer (a_keyValuePair1.first, a_keyValuePair2.first);
			}
			
			template <typename T, typename U, typename W> void NavigableLinkedMap <T, U, W>::insertNewElementAtEnd (key_type const a_key, optional <mapped_type> a_value) {
				mapped_type & l_insertedElementValue = (*i_keyToValueMap) [a_key];
				Links & l_insertedElementLinks = (*i_keyToLinksMap) [a_key];
				if (i_lastKey->has_value ()) {
					(*i_keyToLinksMap) [**i_lastKey].setNextKey (a_key);
				}
				l_insertedElementLinks.setPreviousKey (*i_lastKey); 
				*i_lastKey = a_key;
				if (!i_firstKey->has_value ()) {
					*i_firstKey = a_key;
				}
				if (a_value.has_value ()) {
					l_insertedElementValue = *a_value;	
				}
			}
			
			template <typename T, typename U, typename W> void NavigableLinkedMap <T, U, W>::insertNewElementAtMiddle (key_type const a_positionKey, key_type const a_key, optional <mapped_type> a_value) {
				Links & l_foundElementLinks = (*i_keyToLinksMap) [a_positionKey];
				mapped_type & l_insertedElementValue = (*i_keyToValueMap) [a_key];
				Links & l_insertedElementLinks = (*i_keyToLinksMap) [a_key];
				optional <key_type> l_previousKey = l_foundElementLinks.getPreviousKey ();
				if (l_previousKey == nullopt) {
					*i_firstKey = a_key;
				}
				else {
					Links & l_previousElementLinks = (*i_keyToLinksMap) [*l_previousKey];
					l_previousElementLinks.setNextKey (a_key);
				}
				l_insertedElementLinks.setPreviousKey (l_foundElementLinks.getPreviousKey ()); 
				l_insertedElementLinks.setNextKey (a_positionKey); 
				l_insertedElementValue = *a_value; 
				l_foundElementLinks.setPreviousKey (a_key); 
			}
			
			template <typename T, typename U, typename W> void NavigableLinkedMap <T, U, W>::updateElement (key_type const a_key, mapped_type a_value) {
				mapped_type & l_updatedElementValue = i_keyToValueMap->at (a_key);
				l_updatedElementValue = a_value; 
			}
			
			template <typename T, typename U, typename W> NavigableLinkedMap <T, U, W>::NavigableLinkedMap (key_compare const & a_keysComparer) : i_keyToValueMap (new map <key_type, mapped_type, key_compare> (a_keysComparer)), i_keyToLinksMap (new map <key_type, Links, key_compare> ( (key_compare) a_keysComparer)), i_firstKey (new optional <key_type> ()), i_lastKey (new optional <key_type> ()) {
			}
			
			template <typename T, typename U, typename W> template <typename V> NavigableLinkedMap <T, U, W>::NavigableLinkedMap (V a_iteratorPointedAtFirstElement, V a_iteratorPointedAtLastElementNotIncluded, key_compare const & a_keysComparer) : i_keyToValueMap (new map <key_type, mapped_type, key_compare> (a_keysComparer)), i_keyToLinksMap (new map <key_type, Links, key_compare> ( (key_compare) a_keysComparer)), i_firstKey (new optional <key_type> ()), i_lastKey (new optional <key_type> ()) {
				this->insert (a_iteratorPointedAtFirstElement, a_iteratorPointedAtLastElementNotIncluded);
			}
			
			template <typename T, typename U, typename W> NavigableLinkedMap <T, U, W>::NavigableLinkedMap (initializer_list <value_type> a_initializer, key_compare const & a_keysComparer) : i_keyToValueMap (new map <key_type, mapped_type, key_compare> (a_keysComparer)), i_keyToLinksMap (new map <key_type, Links, key_compare> ( (key_compare) a_keysComparer)), i_firstKey (new optional <key_type> ()), i_lastKey (new optional <key_type> ()) {
				for (value_type const & l_keyValuePair: a_initializer) {
					insert (l_keyValuePair);
				}
			}
			
			template <typename T, typename U, typename W> NavigableLinkedMap <T, U, W>::NavigableLinkedMap (NavigableLinkedMap <key_type, mapped_type, key_compare> const & a_navigableLinkedMap) : i_keyToValueMap (new map <key_type, mapped_type, key_compare> (*(a_navigableLinkedMap.i_keyToValueMap))), i_keyToLinksMap (new map <key_type, Links, key_compare> (*(a_navigableLinkedMap.i_keyToLinksMap))), i_firstKey (new optional <key_type> (*(a_navigableLinkedMap.i_firstKey))), i_lastKey (new optional <key_type> (*(a_navigableLinkedMap.i_lastKey))) {
			}
			
			template <typename T, typename U, typename W> NavigableLinkedMap <T, U, W>::~NavigableLinkedMap () {
				delete i_keyToValueMap;
				i_keyToValueMap = nullptr;
				delete i_keyToLinksMap;
				i_keyToLinksMap = nullptr;
				delete i_firstKey;
				i_firstKey = nullptr;
				delete i_lastKey;
				i_lastKey = nullptr;
			}
			
			template <typename T, typename U, typename W> NavigableLinkedMap <T, U, W> & NavigableLinkedMap <T, U, W>::operator = (NavigableLinkedMap <key_type, mapped_type, key_compare> const & a_navigableLinkedMap) {
				*i_keyToValueMap = *(a_navigableLinkedMap.i_keyToValueMap);
				*i_keyToLinksMap = *(a_navigableLinkedMap.i_keyToLinksMap);
				*i_firstKey = *(a_navigableLinkedMap.i_firstKey);
				*i_lastKey = *(a_navigableLinkedMap.i_lastKey);
				return *this;
			}
			
			template <typename T, typename U, typename W> typename NavigableLinkedMap <T, U, W>::iterator NavigableLinkedMap <T, U, W>::begin () {
				return iterator (*this, *i_firstKey);
			}
			
			template <typename T, typename U, typename W> typename NavigableLinkedMap <T, U, W>::const_iterator NavigableLinkedMap <T, U, W>::begin () const {
				return const_iterator (*this, *i_firstKey);
			}
			
			template <typename T, typename U, typename W> typename NavigableLinkedMap <T, U, W>::iterator NavigableLinkedMap <T, U, W>::end () {
				return iterator (*this, nullopt);
			}
			
			template <typename T, typename U, typename W> typename NavigableLinkedMap <T, U, W>::const_iterator NavigableLinkedMap <T, U, W>::end () const {
				return const_iterator (*this, nullopt);
			}
			
			template <typename T, typename U, typename W> typename NavigableLinkedMap <T, U, W>::reverse_iterator NavigableLinkedMap <T, U, W>::rbegin () {
				return reverse_iterator (end ());
			}
			
			template <typename T, typename U, typename W> typename NavigableLinkedMap <T, U, W>::const_reverse_iterator NavigableLinkedMap <T, U, W>::rbegin () const {
				return const_reverse_iterator (end ());
			}
			
			template <typename T, typename U, typename W> typename NavigableLinkedMap <T, U, W>::reverse_iterator NavigableLinkedMap <T, U, W>::rend () {
				return reverse_iterator (begin ());
			}
			
			template <typename T, typename U, typename W> typename NavigableLinkedMap <T, U, W>::const_reverse_iterator NavigableLinkedMap <T, U, W>::rend () const {
				return const_reverse_iterator (begin ());
			}
			
			template <typename T, typename U, typename W> typename NavigableLinkedMap <T, U, W>::const_iterator NavigableLinkedMap <T, U, W>::cbegin () const noexcept {
				return const_iterator (*this, *i_firstKey);
			}
			
			template <typename T, typename U, typename W> typename NavigableLinkedMap <T, U, W>::const_iterator NavigableLinkedMap <T, U, W>::cend () const noexcept {
				return const_iterator (*this, nullopt);
			}
			
			template <typename T, typename U, typename W> typename NavigableLinkedMap <T, U, W>::const_reverse_iterator NavigableLinkedMap <T, U, W>::crbegin () const noexcept {
				return const_reverse_iterator (cend ());
			}
			
			template <typename T, typename U, typename W> typename NavigableLinkedMap <T, U, W>::const_reverse_iterator NavigableLinkedMap <T, U, W>::crend () const noexcept {
				return const_reverse_iterator (cbegin ());
			}
			
			template <typename T, typename U, typename W> bool NavigableLinkedMap <T, U, W>::empty () const {
				i_keyToValueMap->empty ();
				return i_keyToLinksMap->empty ();
			}
			
			template <typename T, typename U, typename W> typename NavigableLinkedMap <T, U, W>::size_type NavigableLinkedMap <T, U, W>::size () const {
				return i_keyToValueMap->size ();
			}
			
			template <typename T, typename U, typename W> typename NavigableLinkedMap <T, U, W>::size_type NavigableLinkedMap <T, U, W>::max_size () const {
				return i_keyToValueMap->max_size ();
			}
			
			template <typename T, typename U, typename W> typename NavigableLinkedMap <T, U, W>::mapped_type & NavigableLinkedMap <T, U, W>::operator []  (key_type const & a_key) {
				Locker l_locker (&i_mutex) ;
				if (i_keyToValueMap->count (a_key) == 0) {
					insertNewElementAtEnd (a_key, nullopt);
				}
				else {
				}
				return (*i_keyToValueMap) [a_key];
			}
			
			template <typename T, typename U, typename W> typename NavigableLinkedMap <T, U, W>::mapped_type & NavigableLinkedMap <T, U, W>::at (key_type const & a_key) {
				return i_keyToValueMap->at (a_key);
			}
			
			template <typename T, typename U, typename W> typename NavigableLinkedMap <T, U, W>::mapped_type const & NavigableLinkedMap <T, U, W>::at (key_type const & a_key) const {
				return i_keyToValueMap->at (a_key);
			}
			
			template <typename T, typename U, typename W> pair <typename NavigableLinkedMap <T, U, W>::iterator, bool> NavigableLinkedMap <T, U, W>::insert (value_type const & a_keyValuePair) {
				Locker l_locker (&i_mutex);
				bool l_isNewlyInserted = false;
				if (i_keyToValueMap->count (a_keyValuePair.first) == 0) {
					l_isNewlyInserted = true;
					insertNewElementAtEnd (a_keyValuePair.first, a_keyValuePair.second);
				}
				else {
					updateElement (a_keyValuePair.first, a_keyValuePair.second);
				}
				return pair (iterator (*this, a_keyValuePair.first), l_isNewlyInserted);
			}
			
			template <typename T, typename U, typename W> typename NavigableLinkedMap <T, U, W>::iterator NavigableLinkedMap <T, U, W>::insert (iterator a_position, value_type const & a_keyValuePair) {
				Locker l_locker (&i_mutex);
				if (i_keyToValueMap->count (a_keyValuePair.first) == 0) {
					if (i_keyToValueMap->count ((*a_position).first) == 0) {
						insertNewElementAtEnd (a_keyValuePair.first, a_keyValuePair.second);
					}
					else {
						insertNewElementAtMiddle ((*a_position).first, a_keyValuePair.first, a_keyValuePair.second);
					}
				}
				else {
					updateElement (a_keyValuePair.first, a_keyValuePair.second);
				}
				return iterator (*this, a_keyValuePair.first);
			}
			
			template <typename T, typename U, typename W> template <typename V> void NavigableLinkedMap <T, U, W>::insert (V a_iteratorPointedAtFirstElement, V a_iteratorPointedAtLastElementNotIncluded) {
				for (V l_iterator = a_iteratorPointedAtFirstElement; l_iterator != a_iteratorPointedAtLastElementNotIncluded; l_iterator++) {
					insert (*l_iterator);
				}
			}
			
			template <typename T, typename U, typename W> void NavigableLinkedMap <T, U, W>::erase (iterator a_position) {
				erase ((*a_position).first);
			}
			
			template <typename T, typename U, typename W> typename NavigableLinkedMap <T, U, W>::size_type NavigableLinkedMap <T, U, W>::erase (key_type const & a_key) {
				Locker l_locker (&i_mutex);
				if (i_keyToValueMap->count (a_key) == 0) {
					return 0;
				}
				else {
					Links & l_foundElementLinks = (*i_keyToLinksMap) [a_key];
					optional <key_type> l_previousKey = l_foundElementLinks.getPreviousKey (); 
					optional <key_type> l_nextKey = l_foundElementLinks.getNextKey (); 
					if (l_previousKey.has_value ()) {
						Links & l_previousElementLinks = (*i_keyToLinksMap) [*l_previousKey];
						if (l_nextKey.has_value ()) {
							Links & l_nextElementLinks = (*i_keyToLinksMap) [*l_nextKey];
							l_previousElementLinks.setNextKey (l_nextKey);
							l_nextElementLinks.setPreviousKey (l_previousKey);
						}
						else {
							l_previousElementLinks.setNextKey (nullopt);
							*i_lastKey = l_previousKey;
						}
					}
					else {
						if (l_nextKey.has_value ()) {
							Links & l_nextElementLinks = (*i_keyToLinksMap) [*l_nextKey];
							*i_firstKey = l_nextKey;
							l_nextElementLinks.setPreviousKey (nullopt);
						}
						else {
							*i_firstKey = nullopt;
							*i_lastKey = nullopt;
						}
					}
					i_keyToValueMap->erase (a_key);
					i_keyToLinksMap->erase (a_key);
					return 1;
				}
			}
			
     		template <typename T, typename U, typename W> void NavigableLinkedMap <T, U, W>::erase (iterator a_iteratorPointedAtFirstElement, iterator a_iteratorPointedAtLastElementNotIncluded) {
				for (NavigableLinkedMap <key_type, mapped_type, key_compare>::iterator l_iterator = a_iteratorPointedAtFirstElement; l_iterator != a_iteratorPointedAtLastElementNotIncluded; l_iterator++) {
					erase (l_iterator);
				}
			}
			
			template <typename T, typename U, typename W> void NavigableLinkedMap <T, U, W>::swap (NavigableLinkedMap <key_type, mapped_type, key_compare> & a_navigableLinkedMap) {
				map <key_type, mapped_type, key_compare> * l_keyToValueMapSaved = i_keyToValueMap;
				map <key_type, Links, key_compare> * l_keyToLinksMapSaved = i_keyToLinksMap;
				i_keyToValueMap = a_navigableLinkedMap.i_keyToValueMap;
				i_keyToLinksMap = a_navigableLinkedMap.i_keyToLinksMap;
				a_navigableLinkedMap.i_keyToValueMap = l_keyToValueMapSaved;
				a_navigableLinkedMap.i_keyToLinksMap = l_keyToLinksMapSaved;
				optional <key_type> * l_firstKeySaved = i_firstKey;
				i_firstKey = a_navigableLinkedMap.i_firstKey;
				a_navigableLinkedMap.i_firstKey = l_firstKeySaved;
				optional <key_type> * l_lastKeySaved = i_lastKey;
				i_lastKey = a_navigableLinkedMap.i_lastKey;
				a_navigableLinkedMap.i_lastKey = l_lastKeySaved;
			}
			
			template <typename T, typename U, typename W> void NavigableLinkedMap <T, U, W>::clear () {
				i_keyToValueMap->clear ();
				i_keyToLinksMap->clear ();
				*i_firstKey = nullopt;
				*i_lastKey = nullopt;
			}
			
			template <typename T, typename U, typename W> template <typename ... V> pair <typename NavigableLinkedMap <T, U, W>::iterator, bool> NavigableLinkedMap <T, U, W>::emplace (V && ... a_arguments) {
				Locker l_locker (&i_mutex);
				pair <key_type &, mapped_type &> l_keyValuePair = getKeyValuePair (a_arguments...);
				T & l_key = l_keyValuePair.first;
				U & l_value = l_keyValuePair.second;
				bool l_isNewlyInserted = false;
				if (i_keyToValueMap->count (l_key) == 0) {
					l_isNewlyInserted = true;
					if (i_lastKey->has_value ()) {
						(*i_keyToLinksMap) [**i_lastKey].setNextKey (l_key);
					}
					i_keyToValueMap->emplace (l_key, l_value);
					i_keyToLinksMap->emplace (l_key, Links (*i_lastKey, nullopt));
					*i_lastKey = l_key;
					if (!i_firstKey->has_value ()) {
						*i_firstKey = l_key;
					}
				}
				else {
				}
				return pair (iterator (*this, l_key), l_isNewlyInserted);
			}
			
			template <typename T, typename U, typename W> template <typename ... V> typename NavigableLinkedMap <T, U, W>::iterator NavigableLinkedMap <T, U, W>::emplace_hint (const_iterator a_position, V && ... a_arguments) {
				Locker l_locker (&i_mutex);
				pair <key_type &, mapped_type &> l_keyValuePair = getKeyValuePair (a_arguments...);
				key_type & l_key = l_keyValuePair.first;
				mapped_type & l_value = l_keyValuePair.second;
				bool l_isNewlyInserted = false;
				if (i_keyToValueMap->count (l_key) == 0) {
					l_isNewlyInserted = true;
					if (i_keyToValueMap->count (a_position->first) == 0) {
						return emplace (a_arguments...).first;
					}
					else {
						Links & l_foundElementLinks = (*i_keyToLinksMap) [a_position->first];
						optional <key_type> l_previousKey = l_foundElementLinks.getPreviousKey ();
						i_keyToValueMap->emplace (l_key, l_value);
						i_keyToLinksMap->emplace (l_key, Links (l_previousKey, a_position->first));
						if (!l_previousKey.has_value ()) {
							*i_firstKey = l_key;
						}
						else {
							Links & l_previousElementLinks = (*i_keyToLinksMap) [*l_previousKey];
							l_previousElementLinks.setNextKey (l_key); 
						}
						l_foundElementLinks.setPreviousKey (l_key); 
					}
				}
				else {
				}
				return iterator (*this, l_key);
			}
			
			template <typename T, typename U, typename W> typename NavigableLinkedMap <T, U, W>::key_compare NavigableLinkedMap <T, U, W>::key_comp () const {
				return i_keyToValueMap->key_comp ();
			}
			
			template <typename T, typename U, typename W> typename NavigableLinkedMap <T, U, W>::value_compare NavigableLinkedMap <T, U, W>::value_comp () const {
				return value_compare (key_comp ());
			}
			
			template <typename T, typename U, typename W> typename NavigableLinkedMap <T, U, W>::iterator NavigableLinkedMap <T, U, W>::find (key_type const & a_key) {
				if (i_keyToValueMap->count (a_key) == 0) {
					return iterator (*this, nullopt);
				}
				else {
					return iterator (*this, a_key);
				}
			}
			
			template <typename T, typename U, typename W> typename NavigableLinkedMap <T, U, W>::const_iterator NavigableLinkedMap <T, U, W>::find (key_type const & a_key) const {
				if (i_keyToValueMap->count (a_key) == 0) {
					return const_iterator (*this, nullopt);
				}
				else {
					return const_iterator (*this, a_key);
				}
			}
			
			template <typename T, typename U, typename W> typename NavigableLinkedMap <T, U, W>::size_type NavigableLinkedMap <T, U, W>::count (key_type const & a_key) const {
				return i_keyToValueMap->count (a_key);
			}
			
			template <typename T, typename U, typename W> typename NavigableLinkedMap <T, U, W>::iterator NavigableLinkedMap <T, U, W>::lower_bound (key_type const & a_key) {
				key_compare l_keyComparer = this->key_comp ();
				for (value_type const & l_keyValuePair: *this) {
					if (!l_keyComparer (l_keyValuePair.first, a_key)) {
						return iterator (*this, l_keyValuePair.first); 
					}
				}
				return end ();
			}
			
			template <typename T, typename U, typename W> typename NavigableLinkedMap <T, U, W>::const_iterator NavigableLinkedMap <T, U, W>::lower_bound (key_type const & a_key) const {
				key_compare l_keyComparer = this->key_comp ();
				for (value_type const & l_keyValuePair: *this) {
					if (!l_keyComparer (l_keyValuePair.first, a_key)) {
						return const_iterator (*this, l_keyValuePair.first); 
					}
				}
				return cend ();
			}
			
			template <typename T, typename U, typename W> typename NavigableLinkedMap <T, U, W>::iterator NavigableLinkedMap <T, U, W>::upper_bound (key_type const & a_key) {
				key_compare l_keyComparer = this->key_comp ();
				for (value_type const & l_keyValuePair: *this) {
					if (l_keyComparer (a_key, l_keyValuePair.first)) {
						return iterator (*this, l_keyValuePair.first); 
					}
				}
				return end ();
			}
			
			template <typename T, typename U, typename W> typename NavigableLinkedMap <T, U, W>::const_iterator NavigableLinkedMap <T, U, W>::upper_bound (key_type const & a_key) const {
				key_compare l_keyComparer = this->key_comp ();
				for (value_type const & l_keyValuePair: *this) {
					if (l_keyComparer (a_key, l_keyValuePair.first)) {
						return const_iterator (*this, l_keyValuePair.first); 
					}
				}
				return cend ();
			}
			
			template <typename T, typename U, typename W> pair <typename NavigableLinkedMap <T, U, W>::const_iterator, typename NavigableLinkedMap <T, U, W>::const_iterator> NavigableLinkedMap <T, U, W>::equal_range (key_type const & a_key) const {
				const_iterator l_lowerBoundIterator = lower_bound (a_key);
				if (l_lowerBoundIterator != cend () && l_lowerBoundIterator->first == a_key) {
					iterator l_nextToLowerBoundIterator = l_lowerBoundIterator;
					l_nextToLowerBoundIterator ++;
					return pair <iterator, iterator> (l_lowerBoundIterator, l_nextToLowerBoundIterator);
				}
				else {
					return pair <const_iterator, const_iterator> (l_lowerBoundIterator, l_lowerBoundIterator);
				}
			}
			
			template <typename T, typename U, typename W> pair <typename NavigableLinkedMap <T, U, W>::iterator, typename NavigableLinkedMap <T, U, W>::iterator> NavigableLinkedMap <T, U, W>::equal_range (key_type const & a_key) {
				iterator l_lowerBoundIterator = lower_bound (a_key);
				if (l_lowerBoundIterator != end () && l_lowerBoundIterator->first == a_key) {
					iterator l_nextToLowerBoundIterator = l_lowerBoundIterator;
					l_nextToLowerBoundIterator ++;
					return pair <iterator, iterator> (l_lowerBoundIterator, l_nextToLowerBoundIterator);
				}
				else {
					return pair <iterator, iterator> (l_lowerBoundIterator, l_lowerBoundIterator);
				}
			}
			
			template <typename T, typename U, typename W> typename NavigableLinkedMap <T, U, W>::allocator_type NavigableLinkedMap <T, U, W>::get_allocator () const {
				return i_keyToValueMap->get_allocator ();
			}
			
			template <typename T, typename U, typename W> void NavigableLinkedMap <T, U, W>::BaseIterator::goToNextElement () {
				if (i_currentKey.has_value ()) {
					try {
						Links & l_currentElementLinks = i_keyToLinksMap->at (*i_currentKey);
						i_currentKey = l_currentElementLinks.getNextKey ();
					}
					catch (out_of_range l_exception) {
						i_currentKey  = nullopt;
					}
				}
				else {
				}
			}
			
			template <typename T, typename U, typename W> void NavigableLinkedMap <T, U, W>::BaseIterator::goToPreviousElement () {
				if (i_currentKey.has_value ()) {
					try {
						Links & l_currentElementLinks = i_keyToLinksMap->at (*i_currentKey);
						// If the current element is the first element, the past-the-end-element becomes the current element.
						i_currentKey = l_currentElementLinks.getPreviousKey ();
					}
					catch (out_of_range l_exception) {
						i_currentKey  = nullopt;
					}
				}
				else {
					i_currentKey  = *i_lastKey;
				}
			}
			
			template <typename T, typename U, typename W> NavigableLinkedMap <T, U, W>::BaseIterator::BaseIterator (NavigableLinkedMap <key_type, mapped_type, key_compare> const & a_navigableLinkedMap, optional <key_type> a_currentKey) : i_keyToValueMap (a_navigableLinkedMap.i_keyToValueMap), i_keyToLinksMap (a_navigableLinkedMap.i_keyToLinksMap), i_firstKey (a_navigableLinkedMap.i_firstKey), i_lastKey (a_navigableLinkedMap.i_lastKey), i_currentKey (a_currentKey) {
			}
			
			template <typename T, typename U, typename W> NavigableLinkedMap <T, U, W>::BaseIterator::BaseIterator (BaseIterator const & a_originalIterator) : i_keyToValueMap (a_originalIterator.i_keyToValueMap), i_keyToLinksMap (a_originalIterator.i_keyToLinksMap), i_firstKey (a_originalIterator.i_firstKey), i_lastKey (a_originalIterator.i_lastKey), i_currentKey (a_originalIterator.i_currentKey) {
			}
			
			template <typename T, typename U, typename W> bool NavigableLinkedMap <T, U, W>::BaseIterator::operator == (BaseIterator const & a_iteratorToBeCompared) const {
				return (i_currentKey == a_iteratorToBeCompared.i_currentKey);
			}
			
			template <typename T, typename U, typename W> bool NavigableLinkedMap <T, U, W>::BaseIterator::operator != (BaseIterator const & a_iteratorToBeCompared) const {
				return (i_currentKey != a_iteratorToBeCompared.i_currentKey);
			}
			
			template <typename T, typename U, typename W> NavigableLinkedMap <T, U, W>::NonConstantIterator::NonConstantIterator (NavigableLinkedMap <key_type, mapped_type, key_compare> const & a_navigableLinkedMap, optional <key_type> a_currentKey) : BaseIterator (a_navigableLinkedMap, a_currentKey) {
			}
			
			template <typename T, typename U, typename W> NavigableLinkedMap <T, U, W>::NonConstantIterator::NonConstantIterator (BaseIterator const & a_originalIterator) : BaseIterator (a_originalIterator) {
			}
							
			template <typename T, typename U, typename W> typename NavigableLinkedMap <T, U, W>::NonConstantIterator & NavigableLinkedMap <T, U, W>::NonConstantIterator::operator ++ () {
				this->goToNextElement ();
				return *this;
			}
			
			template <typename T, typename U, typename W> typename NavigableLinkedMap <T, U, W>::NonConstantIterator NavigableLinkedMap <T, U, W>::NonConstantIterator::operator ++ (int) {
				NonConstantIterator l_copiedIterator (*this);
				this->goToNextElement ();
				return l_copiedIterator;
			}
			
			template <typename T, typename U, typename W> typename NavigableLinkedMap <T, U, W>::NonConstantIterator & NavigableLinkedMap <T, U, W>::NonConstantIterator::operator -- () {
				this->goToPreviousElement ();
				return *this;
			}
			
			template <typename T, typename U, typename W> typename NavigableLinkedMap <T, U, W>::NonConstantIterator NavigableLinkedMap <T, U, W>::NonConstantIterator::operator -- (int) {
				NonConstantIterator l_copiedIterator (*this);
				this->goToPreviousElement ();
				return l_copiedIterator;
			}
			
			template <typename T, typename U, typename W> typename NavigableLinkedMap <T, U, W>::NonConstantIterator::value_type & NavigableLinkedMap <T, U, W>::NonConstantIterator::operator * () {
				if (this->i_currentKey.has_value ()) {
					try {
						return this->i_keyToValueMap->find (*(this->i_currentKey)).operator * ();
					}
					catch (out_of_range l_exception) {
						throw l_exception;
					}
				}
				else {
					throw out_of_range ("The key does not exist.");
				}
			}
			
			template <typename T, typename U, typename W> typename NavigableLinkedMap <T, U, W>::NonConstantIterator::value_type * NavigableLinkedMap <T, U, W>::NonConstantIterator::operator -> () {
				if (this->i_currentKey.has_value ()) {
					try {
						return this->i_keyToValueMap->find (*(this->i_currentKey)).operator -> ();
						
					}
					catch (out_of_range l_exception) {
						throw l_exception;
					}
				}
				else {
					throw out_of_range ("The key does not exist.");
				}
			}
			
			template <typename T, typename U, typename W> NavigableLinkedMap <T, U, W>::ConstantIterator::ConstantIterator (NavigableLinkedMap <key_type, mapped_type, key_compare> const & a_navigableLinkedMap, optional <key_type> a_currentKey) : BaseIterator (a_navigableLinkedMap, a_currentKey) {
			}
			
			template <typename T, typename U, typename W> NavigableLinkedMap <T, U, W>::ConstantIterator::ConstantIterator (BaseIterator const & a_originalIterator) : BaseIterator (a_originalIterator) {
			}
							
			template <typename T, typename U, typename W> typename NavigableLinkedMap <T, U, W>::ConstantIterator & NavigableLinkedMap <T, U, W>::ConstantIterator::operator ++ () {
				this->goToNextElement ();
				return *this;
			}
			
			template <typename T, typename U, typename W> typename NavigableLinkedMap <T, U, W>::ConstantIterator NavigableLinkedMap <T, U, W>::ConstantIterator::operator ++ (int) {
				ConstantIterator l_copiedIterator (*this);
				this->goToNextElement ();
				return l_copiedIterator;
			}
			
			template <typename T, typename U, typename W> typename NavigableLinkedMap <T, U, W>::ConstantIterator & NavigableLinkedMap <T, U, W>::ConstantIterator::operator -- () {
				this->goToPreviousElement ();
				return *this;
			}
			
			template <typename T, typename U, typename W> typename NavigableLinkedMap <T, U, W>::ConstantIterator NavigableLinkedMap <T, U, W>::ConstantIterator::operator -- (int) {
				ConstantIterator l_copiedIterator (*this);
				this->goToPreviousElement ();
				return l_copiedIterator;
			}
			
#ifdef GCC
			template <typename T, typename U, typename W> typename NavigableLinkedMap <T, U, W>::ConstantIterator::value_type & NavigableLinkedMap <T, U, W>::ConstantIterator::operator * () {
#else
			template <typename T, typename U, typename W> typename NavigableLinkedMap <T, U, W>::ConstantIterator::NonConstantvalue_type const & NavigableLinkedMap <T, U, W>::ConstantIterator::operator * () {
#endif
				if (this->i_currentKey.has_value ()) {
					try {
						return (const_cast <map <key_type, mapped_type, key_compare> const *> (this->i_keyToValueMap))->find (*(this->i_currentKey)).operator * ();
					}
					catch (out_of_range l_exception) {
						throw l_exception;
					}
				}
				else {
					throw out_of_range ("The key does not exist.");
				}
			}
			
#ifdef GCC
			template <typename T, typename U, typename W> typename NavigableLinkedMap <T, U, W>::ConstantIterator::value_type * NavigableLinkedMap <T, U, W>::ConstantIterator::operator -> () {
#else
			template <typename T, typename U, typename W> typename NavigableLinkedMap <T, U, W>::ConstantIterator::NonConstantvalue_type const * NavigableLinkedMap <T, U, W>::ConstantIterator::operator -> () {
#endif
				if (this->i_currentKey.has_value ()) {
					try {
						return (const_cast <map <key_type, mapped_type, key_compare> const *> (this->i_keyToValueMap))->find (*(this->i_currentKey)).operator -> ();
						
					}
					catch (out_of_range l_exception) {
						throw l_exception;
					}
				}
				else {
					throw out_of_range ("The key does not exist.");
				}
			}
		}
	}
}

'::theBiasPlanet::coreUtilities::locksHandling::Locker'クラスは、そのインスタンスが生存している間、指定されたミューテックスをロックする私のクラスだ。

'insert'または'emplace_hint'の呼び出しで指定された位置は、スタンダード'map'の場合のようなただのヒントではなく、結果に反映されることが保証されている。


4: あるテストコード


Hypothesizer 7
正直に言って、私のスタンダード'map'互換要素群順序維持マップを徹底的にテストしてはいない。しかし、少しはテストしており、少なくとも、各メソッドを1度は呼んだ。

以下が、そのテストコードだ。

theBiasPlanet/tests/navigableLinkedMapTest1/Test1Test.hpp

@C++ ソースコード
#include <string>

using namespace ::std;

namespace theBiasPlanet {
	namespace tests {
		namespace navigableLinkedMapTest1 {
			class Test1Test {
				public:
					class StringsComparer : public less <string> {
						private:
							bool i_isInReverseMode;
						public:
							StringsComparer (bool const a_isInReverseMode = false);
							bool operator () (string const & a_leftOperand, string const & a_rightOperand) const;
					};
					static void test (string const & a_string);
			};
		}
	}
}

theBiasPlanet/tests/navigableLinkedMapTest1/Test1Test.cpp

@C++ ソースコード
#include "theBiasPlanet/tests/navigableLinkedMapTest1/Test1Test.hpp"
#include "theBiasPlanet/coreUtilities/collections/NavigableLinkedMap.hpp"
#include <iostream>
#include <string>

#include <map>

using namespace ::std;
using namespace ::theBiasPlanet::coreUtilities::collections;

namespace theBiasPlanet {
	namespace tests {
		namespace navigableLinkedMapTest1 {
			Test1Test::StringsComparer::StringsComparer (bool const a_isInReverseMode) : i_isInReverseMode (a_isInReverseMode) {
			}
			
			bool Test1Test::StringsComparer::operator () (string const & a_leftOperand, string const & a_rightOperand) const {
				if (!i_isInReverseMode) {
        			return a_leftOperand < a_rightOperand;
				}
				else {
        			return a_leftOperand > a_rightOperand;
				}
			}
			
			void Test1Test::test (string const & a_string) {
				map <string, int> l_standardMap;
				l_standardMap  [string ("ddd")] = 4;
				l_standardMap  [string ("ccc")] = 3;
				l_standardMap  [string ("bbb")] = 2;
				l_standardMap  [string ("aaa")] = 1;
				cout << "### The standard map for-loop Start" << endl << flush;
				for (map <string, int>::value_type l_keyValuePair: l_standardMap) {
					cout << "### The key/value are '" << l_keyValuePair.first << "'/'" << l_keyValuePair.second << "'." << endl << flush;
				}
				cout << "### The standard map for-loop End" << endl << endl << flush;
				
				StringsComparer l_normalStringsComparer (false);
				StringsComparer l_reverseStringsComparer (true);
				NavigableLinkedMap <string, int, StringsComparer> l_navigableLinkedMap1 (l_normalStringsComparer);
				l_navigableLinkedMap1 [string ("ddd")] = 4;
				l_navigableLinkedMap1 [string ("ccc")] = 3;
				l_navigableLinkedMap1 [string ("bbb")] = 2;
				l_navigableLinkedMap1 [string ("aaa")] = 1;
				NavigableLinkedMap <string, int, StringsComparer> l_navigableLinkedMap2 (l_reverseStringsComparer);
				l_navigableLinkedMap2 [string ("ddd")] = 4;
				l_navigableLinkedMap2 [string ("ccc")] = 3;
				l_navigableLinkedMap2 [string ("bbb")] = 2;
				l_navigableLinkedMap2 [string ("aaa")] = 1;
				NavigableLinkedMap <string, int, StringsComparer> l_navigableLinkedMap3 (l_navigableLinkedMap1.find (string ("ccc")), l_navigableLinkedMap1.find ("aaa"), l_normalStringsComparer);
				NavigableLinkedMap <string, int, StringsComparer> l_navigableLinkedMap4 ({ {string ("ddd"), 4}, {string ("ccc"), 3}, {string ("bbb"), 2}, {string ("aaa"), 1}}, l_reverseStringsComparer);
				NavigableLinkedMap <string, int, StringsComparer> l_navigableLinkedMap5 (l_navigableLinkedMap1);
				NavigableLinkedMap <string, int, StringsComparer> l_navigableLinkedMap6 (l_navigableLinkedMap2);
				l_navigableLinkedMap6 = l_navigableLinkedMap4;
				
				cout << "### The range-based for-loop of 'l_navigableLinkedMap1' Start" << endl << flush;
				for (NavigableLinkedMap <string, int, StringsComparer>::value_type l_keyValuePair: l_navigableLinkedMap1) {
					cout << "### The key/value are '" << l_keyValuePair.first << "'/'" << l_keyValuePair.second << "'." << endl << flush;
				}
				cout << "### The range-based for-loop of 'l_navigableLinkedMap1' End" << endl << endl << flush;
				
				NavigableLinkedMap <string, int, StringsComparer>::iterator l_iteratorAtEnd = l_navigableLinkedMap2.end ();
				cout << "### The explicit-iterator for-loop of 'l_navigableLinkedMap2' Start" << endl << flush;
				for (NavigableLinkedMap <string, int, StringsComparer>::iterator l_iterator = l_navigableLinkedMap2.begin (); l_iterator != l_iteratorAtEnd; l_iterator ++) {
					cout << "### The key/value are '" << l_iterator->first << "'/'" << l_iterator->second << "'." << endl << flush;
					l_iterator->second ++;
				}
				cout << "### The explicit-iterator for-loop of 'l_navigableLinkedMap2' End" << endl << endl << flush;
				
				cout << "### The explicit-iterator reverse for-loop of 'l_navigableLinkedMap3' Start" << endl << flush;
				NavigableLinkedMap <string, int, StringsComparer>::iterator l_iteratorAtStart = l_navigableLinkedMap3.begin ();
				for (NavigableLinkedMap <string, int, StringsComparer>::iterator l_iterator = l_navigableLinkedMap3.end (); l_iterator != l_iteratorAtStart;) {
					l_iterator --;
					cout << "### The key/value are '" << l_iterator->first << "'/'" << l_iterator->second << "'." << endl << flush;
				}
				cout << "### The explicit-iterator reverse for-loop of 'l_navigableLinkedMap3' End" << endl << endl << flush;
				
				cout << "### The explicit-reverse-iterator for-loop of 'l_navigableLinkedMap4' Start" << endl << flush;
				NavigableLinkedMap <string, int, StringsComparer>::reverse_iterator l_reverseIteratorAtEnd = l_navigableLinkedMap4.rend ();
				for (NavigableLinkedMap <string, int, StringsComparer>::reverse_iterator l_reverseIterator = l_navigableLinkedMap4.rbegin (); l_reverseIterator != l_reverseIteratorAtEnd; l_reverseIterator ++) {
					cout << "### The key/value are '" << (*l_reverseIterator).first << "'/'" << (*l_reverseIterator).second << "'." << endl << flush;
				}
				cout << "### The explicit-reverse-iterator for-loop of 'l_navigableLinkedMap4' End" << endl << endl << flush;
				
				cout << "### The range-based for-loop of 'l_navigableLinkedMap5' Start" << endl << flush;
				for (NavigableLinkedMap <string, int, StringsComparer>::value_type l_keyValuePair: l_navigableLinkedMap5) {
					cout << "### The key/value are '" << l_keyValuePair.first << "'/'" << l_keyValuePair.second << "'." << endl << flush;
				}
				cout << "### The range-based for-loop of 'l_navigableLinkedMap5' End" << endl << endl << flush;
				
				cout << "### The range-based for-loop of 'l_navigableLinkedMap6' Start" << endl << flush;
				for (NavigableLinkedMap <string, int, StringsComparer>::value_type l_keyValuePair: l_navigableLinkedMap6) {
					cout << "### The key/value are '" << l_keyValuePair.first << "'/'" << l_keyValuePair.second << "'." << endl << flush;
				}
				cout << "### The range-based for-loop of 'l_navigableLinkedMap6' End" << endl << endl << flush;
				
				cout << "### Check the emptiness Start" << endl << flush;
				cout << "### 'l_navigableLinkedMap6' is empty: " << l_navigableLinkedMap6.empty () << endl << flush;
				cout << "### 'l_navigableLinkedMap6' is cleared." << endl << flush;
				l_navigableLinkedMap6.clear ();
				cout << "### 'l_navigableLinkedMap6' is empty: " << l_navigableLinkedMap6.empty () << endl << flush;
				cout << "### Check the emptiness End" << endl << endl << flush;
				
				cout << "### The size of 'l_navigableLinkedMap2' is '" << l_navigableLinkedMap2.size () << "'." << endl << endl << flush;
				
				cout << "### The max size of 'l_navigableLinkedMap2' is '" << l_navigableLinkedMap2.max_size () << "'." << endl << endl << flush;
				
				cout << "### The [] operator test of 'l_navigableLinkedMap2' Start." << endl << flush;
				cout << "### The value for 'string (\"bbb\")' is set." << endl << flush;
				l_navigableLinkedMap2 [string ("bbb")] = 10;
				cout << "### The [] operator result for 'string (\"bbb\")' is '" << l_navigableLinkedMap2 [string ("bbb")] << "'." << endl << flush;
				cout << "### The [] operator result for 'string (\"eee\")' is '" << l_navigableLinkedMap2 [string ("eee")] << "'." << endl << flush;
				cout << "### The size is '" << l_navigableLinkedMap2.size () << "'." << endl << flush;
				cout << "### The [] operator test of 'l_navigableLinkedMap2' End." << endl << endl << flush;
				
				cout << "### The at function test of 'l_navigableLinkedMap2' Start." << endl << flush;
				cout << "### The value for 'string (\"bbb\")' is set." << endl << flush;
				l_navigableLinkedMap2.at (string ("bbb")) = 12;
				cout << "### The at function result for 'string (\"bbb\")' is '" << l_navigableLinkedMap2.at (string ("bbb")) << "'." << endl << flush;
				//cout << "### A at function result for 'string (\"fff\")' is '" << l_navigableLinkedMap2.at (string ("fff")) << "'." << endl << flush;
				cout << "### The size of 'l_navigableLinkedMap2' is '" << l_navigableLinkedMap2.size () << "'." << endl << flush;
				cout << "### The at function test of 'l_navigableLinkedMap2' End." << endl << endl << flush;
				
				cout << "### The insert function test of 'l_navigableLinkedMap2' Start." << endl << flush;
				cout << "### The 'string (\"fff\")' element is inserted at the end." << endl << flush;
				l_navigableLinkedMap2.insert (NavigableLinkedMap <string, int, StringsComparer>::value_type (string ("fff"), 6)); 
				cout << "### The 'string (\"ggg\")' element is inserted at the beginning." << endl << flush;
				l_navigableLinkedMap2.insert (l_navigableLinkedMap2.begin (), NavigableLinkedMap <string, int, StringsComparer>::value_type (string ("ggg"), 7)); 
				cout << "### The 'string (\"hhh\")' element is inserted before the string (\"ccc\") element." << endl << flush;
				l_navigableLinkedMap2.insert (l_navigableLinkedMap2.find (string ("ccc")), NavigableLinkedMap <string, int, StringsComparer>::value_type (string ("hhh"), 8)); 
				NavigableLinkedMap <string, int, StringsComparer> l_navigableLinkedMap7 ({ {string ("iii"), 9}, {string ("jjj"), 10}, {string ("kkk"), 11}, {string ("lll"), 12}}, l_reverseStringsComparer);
				cout << "### The 'string (\"iii\")', 'string (\"jjj\")', and 'string (\"kkk\")' elements are inserted at the end." << endl << flush;
				l_navigableLinkedMap2.insert (l_navigableLinkedMap7.begin (), l_navigableLinkedMap7.find (string ("lll"))); 
				for (NavigableLinkedMap <string, int, StringsComparer>::value_type l_keyValuePair: l_navigableLinkedMap2) {
					cout << "### The key/value are '" << l_keyValuePair.first << "'/'" << l_keyValuePair.second << "'." << endl << flush;
				}
				cout << "### The insert function test of 'l_navigableLinkedMap2' End." << endl  << endl<< flush;
				
				cout << "### The erase function test of 'l_navigableLinkedMap2' Start." << endl << flush;
				cout << "### The 'string (\"iii\")' element is erased." << endl << flush;
				l_navigableLinkedMap2.erase (l_navigableLinkedMap7.find (string ("iii")));
				cout << "### The 'string (\"eee\")' element is erased." << endl << flush;
				l_navigableLinkedMap2.erase (string ("eee"));
				cout << "### The 'string (\"jjj\")' element is erased." << endl << flush;
				l_navigableLinkedMap2.erase (l_navigableLinkedMap7.find (string ("jjj")), l_navigableLinkedMap7.find (string ("kkk")));
				for (NavigableLinkedMap <string, int, StringsComparer>::value_type l_keyValuePair: l_navigableLinkedMap2) {
					cout << "### The key/value are '" << l_keyValuePair.first << "'/'" << l_keyValuePair.second << "'." << endl << flush;
				}
				cout << "### The erase function test of 'l_navigableLinkedMap2' End." << endl << endl << flush;
				
				cout << "### The swap function test of 'l_navigableLinkedMap2' with 'l_navigableLinkedMap4' Start." << endl << flush;
				l_iteratorAtStart = l_navigableLinkedMap2.begin ();
				cout << "### The iterator at the beginning of 'l_navigableLinkedMap2' before swap is '" << l_iteratorAtStart->first << "'/'" << l_iteratorAtStart->second << "'." << endl << flush;
				cout << "### 'l_navigableLinkedMap2' is swapped with 'l_navigableLinkedMap4'." << endl << flush;
				l_navigableLinkedMap2.swap (l_navigableLinkedMap4);
				cout << "### The iterator after swap is '" << l_iteratorAtStart->first << "'/'" << l_iteratorAtStart->second << "'." << endl << flush;
				cout << "### Seeing the contents of 'l_navigableLinkedMap2' Start." << endl << flush;
				for (NavigableLinkedMap <string, int, StringsComparer>::value_type l_keyValuePair: l_navigableLinkedMap2) {
					cout << "### The key/value are '" << l_keyValuePair.first << "'/'" << l_keyValuePair.second << "'." << endl << flush;
				}
				cout << "### Seeing the contents of 'l_navigableLinkedMap2' End." << endl << flush;
				cout << "### Seeing the contents of 'l_navigableLinkedMap4' Start." << endl << flush;
				for (NavigableLinkedMap <string, int, StringsComparer>::value_type l_keyValuePair: l_navigableLinkedMap4) {
					cout << "### The key/value are '" << l_keyValuePair.first << "'/'" << l_keyValuePair.second << "'." << endl << flush;
				}
				cout << "### Seeing the contents of 'l_navigableLinkedMap4' End." << endl << flush;
				cout << "### The swap function test of 'l_navigableLinkedMap2' with 'l_navigableLinkedMap4' End." << endl << endl << flush;
				
				cout << "### The emplace function test of 'l_navigableLinkedMap4' Start." << endl << flush;
				cout << "### The 'string (\"eee\")' element is emplaced." << endl << flush;
				l_navigableLinkedMap4.emplace (string ("eee"), 6);
				cout << "### The 'string (\"mmm\")' element is emplaced before the 'string (\"ccc\")' element." << endl << flush;
				l_navigableLinkedMap4.emplace_hint (l_navigableLinkedMap4.find (string ("ccc")), string ("mmm"), 13);
				for (NavigableLinkedMap <string, int, StringsComparer>::value_type l_keyValuePair: l_navigableLinkedMap4) {
					cout << "### The key/value are '" << l_keyValuePair.first << "'/'" << l_keyValuePair.second << "'." << endl << flush;
				}
				cout << "### The emplace function test of 'l_navigableLinkedMap4' End." << endl << endl << flush;
				
				cout << "### The key_comp function test of 'l_navigableLinkedMap1' and 'l_navigableLinkedMap4' Start." << endl << flush;
				cout << "### A key_comp result of 'l_navigableLinkedMap1' for 'string (\"ccc\") <  string (\"bbb\")' is " << (l_navigableLinkedMap1.key_comp ()) (string ("ccc"), string ("bbb")) << "'." << endl << flush;
				cout << "### A key_comp result of 'l_navigableLinkedMap4' for 'string (\"ccc\") <  string (\"bbb\")' is " << (l_navigableLinkedMap4.key_comp ()) (string ("ccc"), string ("bbb")) << "'." << endl << flush;
				cout << "### The key_comp function test of 'l_navigableLinkedMap1' and 'l_navigableLinkedMap4' End." << endl << endl << flush;
				
				cout << "### The value_comp function test of 'l_navigableLinkedMap1' and 'l_navigableLinkedMap4' Start." << endl << flush;
				cout << "### A value_comp result of 'l_navigableLinkedMap1' for 'string (\"ccc\") <  string (\"ddd\")' is " << (l_navigableLinkedMap1.value_comp ()) (NavigableLinkedMap <string, int, StringsComparer>::value_type (string ("ccc"), 3), NavigableLinkedMap <string, int, StringsComparer>::value_type (string ("ddd"), 2)) << "'." << endl << flush;
				cout << "### A value_comp result of 'l_navigableLinkedMap4' for 'string (\"ccc\") <  string (\"ddd\")' is " << (l_navigableLinkedMap4.value_comp ()) (NavigableLinkedMap <string, int, StringsComparer>::value_type (string ("ccc"), 3), NavigableLinkedMap <string, int, StringsComparer>::value_type (string ("ddd"), 2)) << "'." << endl << flush;
				cout << "### The value_comp function test of 'l_navigableLinkedMap1' and 'l_navigableLinkedMap4' End." << endl << endl << flush;
				
				cout << "### The count function test of 'l_navigableLinkedMap4' Start." << endl << flush;
				cout << "### A count result for 'string (\"aaa\")' is " << l_navigableLinkedMap4.count (string ("aaa")) << "'." << endl << flush;
				cout << "### A count result is for 'string (\"nnn\")' " << l_navigableLinkedMap4.count (string ("nnn")) << "'." << endl << flush;
				cout << "### The count function test of 'l_navigableLinkedMap4' End." << endl << endl << flush;
				
				cout << "### The lower_bound function test of 'l_navigableLinkedMap1' and 'l_navigableLinkedMap4' Start." << endl << flush;
				cout << "### A lower_bound result of 'l_navigableLinkedMap1' for 'string (\"ccc\")' is " << (l_navigableLinkedMap1.lower_bound (string ("ccc")))->first << "'." << endl << flush;
				cout << "### A lower_bound result of 'l_navigableLinkedMap1' for 'string (\"nnn\")' is " << ((l_navigableLinkedMap1.lower_bound (string ("nnn"))) == l_navigableLinkedMap1.end ()) << "'." << endl << flush;
				cout << "### A lower_bound result of 'l_navigableLinkedMap4' for 'string (\"ccc\")' is " << (l_navigableLinkedMap4.lower_bound (string ("ccc")))->first << "'." << endl << flush;
				cout << "### A lower_bound result of 'l_navigableLinkedMap4' for 'string (\"nnn\")' is " << ((l_navigableLinkedMap4.lower_bound (string ("nnn"))) == l_navigableLinkedMap4.end ()) << "'." << endl << flush;
				cout << "### The lower_bound function test of 'l_navigableLinkedMap1' and 'l_navigableLinkedMap4' End." << endl << endl << flush;
				
				cout << "### The upper_bound function test of 'l_navigableLinkedMap1' and 'l_navigableLinkedMap4' Start." << endl << flush;
				cout << "### A upper_bound result of 'l_navigableLinkedMap1' for 'string (\"ccc\")' is " << (l_navigableLinkedMap1.upper_bound (string ("ccc")))->first << "'." << endl << flush;
				cout << "### A upper_bound result of 'l_navigableLinkedMap1' for 'string (\"nnn\")' is " << ((l_navigableLinkedMap1.upper_bound (string ("nnn"))) == l_navigableLinkedMap1.end ()) << "'." << endl << flush;
				cout << "### A upper_bound result of 'l_navigableLinkedMap4' for 'string (\"ccc\")' is " << (l_navigableLinkedMap4.upper_bound (string ("ccc")))->first << "'." << endl << flush;
				cout << "### A upper_bound result of 'l_navigableLinkedMap4' for 'string (\"nnn\")' is " << ((l_navigableLinkedMap4.upper_bound (string ("nnn"))) == l_navigableLinkedMap4.end ()) << "'." << endl << flush;
				cout << "### The upper_bound function test of 'l_navigableLinkedMap1' and 'l_navigableLinkedMap4' End." << endl << endl << flush;
				
				cout << "### The equal_range function test of 'l_navigableLinkedMap1' and 'l_navigableLinkedMap4' Start." << endl << flush;
				cout << "### The equal_range result of 'l_navigableLinkedMap1' for 'string (\"ddd\")' is '" << (l_navigableLinkedMap1.equal_range (string ("ddd"))).first->first << "->" << (l_navigableLinkedMap1.equal_range (string ("ddd"))).second->first << "'." << endl << flush;
				cout << "### The equal_range result of 'l_navigableLinkedMap1' for 'string (\"nnn\")' is '" << ((l_navigableLinkedMap1.equal_range (string ("nnn")).first) == l_navigableLinkedMap1.end ()) << "'." << endl << flush;
				cout << "### The equal_range result of 'l_navigableLinkedMap4' for 'string (\"ddd\")' is '" << (l_navigableLinkedMap4.equal_range (string ("ddd"))).first->first << "->" << (l_navigableLinkedMap4.equal_range (string ("ddd"))).second->first << "'." << endl << flush;
				cout << "### The equal_range result of 'l_navigableLinkedMap4' for 'string (\"nnn\")' is '" << ((l_navigableLinkedMap4.equal_range (string ("nnn")).first) == l_navigableLinkedMap4.end ()) << "'." << endl << flush;
				cout << "### The equal_range function test of 'l_navigableLinkedMap1' and 'l_navigableLinkedMap4' End." << endl << endl << flush;
				
				cout << "### The get_allocator function test of 'l_navigableLinkedMap4' Start." << endl << flush;
				l_navigableLinkedMap4.get_allocator ();
				
				cout << "### The get_allocator function test of 'l_navigableLinkedMap4' End." << endl << flush;
				
			}
		}
	}
}

'l_standardMap'は、比較のためにテストしたスタンダード'map'インスタンスだ: その要素群は、挿入された順序で取得されない。

'::theBiasPlanet::tests::navigableLinkedMapTest1::Test1Test::StringsComparer'は、キー比較子であり、指定された2つの文字列キーを、通常の順序または逆順で比較する。'l_normalStringsComparer'と'l_reverseStringsComparer'のいずれが要素群順序維持マップインスタンスに使用されたかは、要素群がマップインスタンスに格納される順序に影響しない、なぜなら、その順序は、キー比較によって決定されるのではなく、要素が挿入された際の指定された要素位置によって決定されるから。しかし、要素群順序維持マップインスタンスに使用された比較子インスタンスは、メソッド、'key_comp'、'value_comp'、'lower_bound'、'upper_bound'、'equal_range'の結果に影響する。

結果は以下のとおりだ。

@出力
### The standard map for-loop Start
### The key/value are 'aaa'/'1'.
### The key/value are 'bbb'/'2'.
### The key/value are 'ccc'/'3'.
### The key/value are 'ddd'/'4'.
### The standard map for-loop End

### The range-based for-loop of 'l_navigableLinkedMap1' Start
### The key/value are 'ddd'/'4'.
### The key/value are 'ccc'/'3'.
### The key/value are 'bbb'/'2'.
### The key/value are 'aaa'/'1'.
### The range-based for-loop of 'l_navigableLinkedMap1' End

### The explicit-iterator for-loop of 'l_navigableLinkedMap2' Start
### The key/value are 'ddd'/'4'.
### The key/value are 'ccc'/'3'.
### The key/value are 'bbb'/'2'.
### The key/value are 'aaa'/'1'.
### The explicit-iterator for-loop of 'l_navigableLinkedMap2' End

### The explicit-iterator reverse for-loop of 'l_navigableLinkedMap3' Start
### The key/value are 'bbb'/'2'.
### The key/value are 'ccc'/'3'.
### The explicit-iterator reverse for-loop of 'l_navigableLinkedMap3' End

### The explicit-reverse-iterator for-loop of 'l_navigableLinkedMap4' Start
### The key/value are 'aaa'/'1'.
### The key/value are 'bbb'/'2'.
### The key/value are 'ccc'/'3'.
### The key/value are 'ddd'/'4'.
### The explicit-reverse-iterator for-loop of 'l_navigableLinkedMap4' End

### The range-based for-loop of 'l_navigableLinkedMap5' Start
### The key/value are 'ddd'/'4'.
### The key/value are 'ccc'/'3'.
### The key/value are 'bbb'/'2'.
### The key/value are 'aaa'/'1'.
### The range-based for-loop of 'l_navigableLinkedMap5' End

### The range-based for-loop of 'l_navigableLinkedMap6' Start
### The key/value are 'ddd'/'4'.
### The key/value are 'ccc'/'3'.
### The key/value are 'bbb'/'2'.
### The key/value are 'aaa'/'1'.
### The range-based for-loop of 'l_navigableLinkedMap6' End

### Check the emptiness Start
### 'l_navigableLinkedMap6' is empty: 0
### 'l_navigableLinkedMap6' is cleared.
### 'l_navigableLinkedMap6' is empty: 1
### Check the emptiness End

### The size of 'l_navigableLinkedMap2' is '4'.

### The max size of 'l_navigableLinkedMap2' is '256204778801521550'.

### The [] operator test of 'l_navigableLinkedMap2' Start.
### The value for 'string ("bbb")' is set.
### The [] operator result for 'string ("bbb")' is '10'.
### The [] operator result for 'string ("eee")' is '0'.
### The size is '5'.
### The [] operator test of 'l_navigableLinkedMap2' End.

### The at function test of 'l_navigableLinkedMap2' Start.
### The value for 'string ("bbb")' is set.
### The at function result for 'string ("bbb")' is '12'.
### The size of 'l_navigableLinkedMap2' is '5'.
### The at function test of 'l_navigableLinkedMap2' End.

### The insert function test of 'l_navigableLinkedMap2' Start.
### The 'string ("fff")' element is inserted at the end.
### The 'string ("ggg")' element is inserted at the beginning.
### The 'string ("hhh")' element is inserted before the string ("ccc") element.
### The 'string ("iii")', 'string ("jjj")', and 'string ("kkk")' elements are inserted at the end.
### The key/value are 'ggg'/'7'.
### The key/value are 'ddd'/'5'.
### The key/value are 'hhh'/'8'.
### The key/value are 'ccc'/'4'.
### The key/value are 'bbb'/'12'.
### The key/value are 'aaa'/'2'.
### The key/value are 'eee'/'0'.
### The key/value are 'fff'/'6'.
### The key/value are 'iii'/'9'.
### The key/value are 'jjj'/'10'.
### The key/value are 'kkk'/'11'.
### The insert function test of 'l_navigableLinkedMap2' End.

### The erase function test of 'l_navigableLinkedMap2' Start.
### The 'string ("iii")' element is erased.
### The 'string ("eee")' element is erased.
### The 'string ("jjj")' element is erased.
### The key/value are 'ggg'/'7'.
### The key/value are 'ddd'/'5'.
### The key/value are 'hhh'/'8'.
### The key/value are 'ccc'/'4'.
### The key/value are 'bbb'/'12'.
### The key/value are 'aaa'/'2'.
### The key/value are 'fff'/'6'.
### The key/value are 'kkk'/'11'.
### The erase function test of 'l_navigableLinkedMap2' End.

### The swap function test of 'l_navigableLinkedMap2' with 'l_navigableLinkedMap4' Start.
### The iterator at the beginning of 'l_navigableLinkedMap2' before swap is 'ggg'/'7'.
### 'l_navigableLinkedMap2' is swapped with 'l_navigableLinkedMap4'.
### The iterator after swap is 'ggg'/'7'.
### Seeing the contents of 'l_navigableLinkedMap2' Start.
### The key/value are 'ddd'/'4'.
### The key/value are 'ccc'/'3'.
### The key/value are 'bbb'/'2'.
### The key/value are 'aaa'/'1'.
### Seeing the contents of 'l_navigableLinkedMap2' End.
### Seeing the contents of 'l_navigableLinkedMap4' Start.
### The key/value are 'ggg'/'7'.
### The key/value are 'ddd'/'5'.
### The key/value are 'hhh'/'8'.
### The key/value are 'ccc'/'4'.
### The key/value are 'bbb'/'12'.
### The key/value are 'aaa'/'2'.
### The key/value are 'fff'/'6'.
### The key/value are 'kkk'/'11'.
### Seeing the contents of 'l_navigableLinkedMap4' End.
### The swap function test of 'l_navigableLinkedMap2' with 'l_navigableLinkedMap4' End.

### The emplace function test of 'l_navigableLinkedMap4' Start.
### The 'string ("eee")' element is emplaced.
### The 'string ("mmm")' element is emplaced before the 'string ("ccc")' element.
### The key/value are 'ggg'/'7'.
### The key/value are 'ddd'/'5'.
### The key/value are 'hhh'/'8'.
### The key/value are 'mmm'/'13'.
### The key/value are 'ccc'/'4'.
### The key/value are 'bbb'/'12'.
### The key/value are 'aaa'/'2'.
### The key/value are 'fff'/'6'.
### The key/value are 'kkk'/'11'.
### The key/value are 'eee'/'6'.
### The emplace function test of 'l_navigableLinkedMap4' End.

### The key_comp function test of 'l_navigableLinkedMap1' and 'l_navigableLinkedMap4' Start.
### A key_comp result of 'l_navigableLinkedMap1' for 'string ("ccc") <  string ("bbb")' is 0'.
### A key_comp result of 'l_navigableLinkedMap4' for 'string ("ccc") <  string ("bbb")' is 1'.
### The key_comp function test of 'l_navigableLinkedMap1' and 'l_navigableLinkedMap4' End.

### The value_comp function test of 'l_navigableLinkedMap1' and 'l_navigableLinkedMap4' Start.
### A value_comp result of 'l_navigableLinkedMap1' for 'string ("ccc") <  string ("ddd")' is 1'.
### A value_comp result of 'l_navigableLinkedMap4' for 'string ("ccc") <  string ("ddd")' is 0'.
### The value_comp function test of 'l_navigableLinkedMap1' and 'l_navigableLinkedMap4' End.

### The count function test of 'l_navigableLinkedMap4' Start.
### A count result for 'string ("aaa")' is 1'.
### A count result is for 'string ("nnn")' 0'.
### The count function test of 'l_navigableLinkedMap4' End.

### The lower_bound function test of 'l_navigableLinkedMap1' and 'l_navigableLinkedMap4' Start.
### A lower_bound result of 'l_navigableLinkedMap1' for 'string ("ccc")' is ddd'.
### A lower_bound result of 'l_navigableLinkedMap1' for 'string ("nnn")' is 1'.
### A lower_bound result of 'l_navigableLinkedMap4' for 'string ("ccc")' is ccc'.
### A lower_bound result of 'l_navigableLinkedMap4' for 'string ("nnn")' is 0'.
### The lower_bound function test of 'l_navigableLinkedMap1' and 'l_navigableLinkedMap4' End.

### The upper_bound function test of 'l_navigableLinkedMap1' and 'l_navigableLinkedMap4' Start.
### A upper_bound result of 'l_navigableLinkedMap1' for 'string ("ccc")' is ddd'.
### A upper_bound result of 'l_navigableLinkedMap1' for 'string ("nnn")' is 1'.
### A upper_bound result of 'l_navigableLinkedMap4' for 'string ("ccc")' is bbb'.
### A upper_bound result of 'l_navigableLinkedMap4' for 'string ("nnn")' is 0'.
### The upper_bound function test of 'l_navigableLinkedMap1' and 'l_navigableLinkedMap4' End.

### The equal_range function test of 'l_navigableLinkedMap1' and 'l_navigableLinkedMap4' Start.
### The equal_range result of 'l_navigableLinkedMap1' for 'string ("ddd")' is 'ddd->ccc'.
### The equal_range result of 'l_navigableLinkedMap1' for 'string ("nnn")' is '1'.
### The equal_range result of 'l_navigableLinkedMap4' for 'string ("ddd")' is 'ddd->hhh'.
### The equal_range result of 'l_navigableLinkedMap4' for 'string ("nnn")' is '0'.
### The equal_range function test of 'l_navigableLinkedMap1' and 'l_navigableLinkedMap4' End.

### The get_allocator function test of 'l_navigableLinkedMap4' Start.
### The get_allocator function test of 'l_navigableLinkedMap4' End.


5: ソースファイル群はここにある


Hypothesizer 7
実は、ソースファイル群はこのZIPファイルに含まれている。ZIPファイルに格納されているプロジェクトをビルドする方法はここで説明されている(ビルド環境をまず構築する必要があるだろう、Linux用はここ or Windows用はここに説明されているとおりに)。


6: 結びとその先


Hypothesizer 7
これで、スタンダード'map'互換要素群順序維持マップを私は得た。

スタンダードコンテナ互換のカスタムコンテナはどんなものでも同じ方法で作成できる。

要素群順序維持マップのためにC++のテンプレート機能を使ったが、気をつけるべき(特に、テンプレート機能をJavaジェネリクス機能のアナロジーで理解したJavaプログラマーは)いくつかの落とし穴を私は発見した(それらに落ちることによって)。それらについて次記事で論じよう


参考資料


<このシリーズの前の記事 | このシリーズの目次 | このシリーズの次の記事>