--- /dev/null
+\r
+#pragma warning(disable:4786)\r
+\r
+#include <set>\r
+#include "sorted_vector.h"\r
+#include <iostream>\r
+#include "assert.h"\r
+#include <time.h>\r
+#include <iomanip>\r
+\r
+struct STest{\r
+ std::string s;\r
+ int id;\r
+};\r
+\r
+STest MakeSTest()\r
+{\r
+ static int id= 0;\r
+ int nLen= rand()%10;\r
+ char* letters[]={"0","1"};\r
+ STest stest;\r
+ \r
+ for(int i=0;i<nLen;i++){\r
+ stest.s+= letters[rand()%2];\r
+ }\r
+ stest.id= ++id;\r
+ return stest;\r
+}\r
+\r
+bool operator<(const STest& t0,const STest& t1)\r
+{\r
+ int nCmp;\r
+ return (nCmp=t0.s.compare(t1.s))<0||nCmp==0 && t0.id<t1.id;\r
+}\r
+\r
+\r
+class SimpTimer{\r
+public:\r
+ SimpTimer(const char* msg):m_msg(msg),m_start(clock()){}\r
+ ~SimpTimer()\r
+ {\r
+ m_stop = clock();\r
+ std::cout << "CPU usage (" << std::setw(35) << m_msg.c_str() << ") = " \r
+ << (double)(m_stop - m_start)/ CLOCKS_PER_SEC\r
+ << " seconds" << std::endl;\r
+ }\r
+private:\r
+ time_t m_start, m_stop;\r
+ std::string m_msg;\r
+};\r
+\r
+\r
+template<class It,class Pred>\r
+bool is_unique(It beg,It beyond,Pred pred)\r
+{\r
+ return std::adjacent_find(beg,beyond,std::not2(pred))==beyond;\r
+}\r
+template<class FwIt,class Pred>\r
+FwIt unsorted_find(FwIt beg,FwIt beyond,Pred pred)\r
+{\r
+ for(FwIt prev ;(prev=beg)!=beyond && ++beg!=beyond;){\r
+ if( pred(*beg,*prev) ){\r
+ return prev;\r
+ }\r
+ }\r
+ return beyond;\r
+}\r
+template<class T>\r
+void TestSet(std::vector<T>& v)\r
+{\r
+ std::set<T> std_set;\r
+ {SimpTimer t("build std::set");\r
+ for(unsigned i=0;i<v.size();i++){\r
+ std_set.insert(v[i]);\r
+ }\r
+ }\r
+ {SimpTimer t("find in std::set");\r
+ for(unsigned i=0;i<v.size();i++){\r
+ std::set<T>::iterator it= std_set.find(v[i]);\r
+ std::set<T>::size_type nCount= std_set.count(v[i]);\r
+ assert( nCount==0 && it==std_set.end()\r
+ || nCount!=0 && it!=std_set.end());\r
+ }\r
+ }\r
+}\r
+template<class T>\r
+void TestSortedVector_AsSet(std::vector<T>& v)\r
+{ \r
+ codeproject::sorted_vector<T,true> svec;\r
+ {SimpTimer t("build sortedvec_set (naiv)");\r
+ for(unsigned i=0;i<v.size();i++){\r
+ svec.insert(v[i]);\r
+ }\r
+ }\r
+ assert(is_unique(svec.begin(),svec.end(),svec.key_comp()));\r
+ codeproject::sorted_vector<T,true> svec1;\r
+ {SimpTimer t("build sortedvec_set (opt.)");\r
+ codeproject::sorted_vector<T,true>::Cont& vec= svec1.get_container();\r
+ for(unsigned i=0;i<v.size();i++){\r
+ vec.push_back(v[i]);\r
+ \r
+ }\r
+ svec1.sort();\r
+ }\r
+ assert(svec==svec1);\r
+ assert(is_unique(svec1.begin(),svec1.end(),svec1.key_comp()));\r
+\r
+ {SimpTimer t("find in sortedvec_set");\r
+ for(unsigned i=0;i<v.size();i++){\r
+ codeproject::sorted_vector<T,true>::iterator it= svec1.find(v[i]);\r
+ codeproject::sorted_vector<T,true>::size_type nCount= svec1.count(v[i]);\r
+ assert( nCount==0 && it==svec1.end()\r
+ || nCount!=0 && it!=svec1.end());\r
+ }\r
+ }\r
+ for(unsigned i=0;i<v.size();i++){svec1.erase(v[i]);}\r
+ assert(svec1.empty());\r
+}\r
+template<class T>\r
+void TestMultiSet(std::vector<T>& v)\r
+{\r
+ std::multiset<T> svec;\r
+\r
+ {SimpTimer t("build multiset");\r
+ for(unsigned i=0;i<v.size();i++){\r
+ svec.insert(v[i]);\r
+ }\r
+ }\r
+ assert(unsorted_find(svec.begin(),svec.end(),svec.key_comp())==svec.end());\r
+ {SimpTimer t("find in multiset");\r
+ for(unsigned i=0;i<v.size();i++){\r
+ std::multiset<T>::iterator it= svec.find(v[i]);\r
+ std::multiset<T>::size_type nCount= svec.count(v[i]);\r
+ assert( nCount==0 && it==svec.end()\r
+ || nCount!=0 && it!=svec.end());\r
+ }\r
+ }\r
+}\r
+\r
+template<class T>\r
+void TestSortedVector_AsMultiSet(std::vector<T>& v)\r
+{\r
+ codeproject::sorted_vector<T> svec;\r
+ {SimpTimer t("build sortedvec_multiset (naiv)");\r
+ for(unsigned i=0;i<v.size();i++){\r
+ svec.insert(v[i]);\r
+ }\r
+ }\r
+ codeproject::sorted_vector<T> svec1;\r
+ {SimpTimer t("build sortedvec_multiset (opt.)");\r
+ codeproject::sorted_vector<T>::Cont& vec= svec1.get_container();\r
+ for(unsigned i=0;i<v.size();i++){\r
+ vec.push_back(v[i]);\r
+ \r
+ }\r
+ svec1.stable_sort();\r
+ }\r
+ assert(svec==svec1);\r
+ assert(unsorted_find(svec.begin(),svec.end(),svec.key_comp())==svec.end());\r
+ {SimpTimer t("find in sortedvec_multiset");\r
+ for(unsigned i=0;i<v.size();i++){\r
+ int n= rand();\r
+ codeproject::sorted_vector<T>::iterator it= svec1.find(v[i]);\r
+ codeproject::sorted_vector<T>::size_type nCount= svec1.count(v[i]);\r
+ assert( nCount==0 && it==svec1.end()\r
+ || nCount!=0 && it!=svec1.end());\r
+ }\r
+ }\r
+/*test various functions*/\r
+ const codeproject::sorted_vector<T> svec2(svec);\r
+ assert(svec==svec2);\r
+ for(unsigned i=0;i<v.size();i++){assert(svec2.find(v[i])!=svec2.end());}\r
+ codeproject::sorted_vector<T> svec3(v.begin(),v.end());\r
+ assert(svec3==svec2);\r
+ codeproject::sorted_vector<T> svec4(v.begin(),v.begin()+(v.end()-v.begin())/2);\r
+ svec4= svec3;\r
+ assert(svec4==svec3);\r
+ while(svec4.size()>0){\r
+ svec4.pop_back();\r
+ }\r
+}\r
+\r
+\r
+\r
+\r
+template<class T>\r
+void ExecTests(std::vector<T>& v)\r
+{\r
+ std::cout << "std::set versus 'sorted_vector as set'" << std::endl; \r
+ TestSet(v);\r
+ TestSortedVector_AsSet(v);\r
+ std::cout << "std::multiset versus 'sorted_vector as multiset'" << std::endl;\r
+ TestMultiSet(v);\r
+ TestSortedVector_AsMultiSet(v);\r
+}\r
+\r
+template<class T,class Pred>\r
+void TestSetOperations(const std::vector<T>& v0,\r
+ const std::vector<T>& v1,\r
+ const std::vector<T>& v2,\r
+ Pred pred)\r
+{\r
+//A) compute the result of the set-operation: (v0-v1)+v2 - intersect(v1,v2)\r
+ codeproject::sorted_vector<T,true,Pred> svec(v0.begin(),v0.end(),pred);\r
+ codeproject::sorted_vector<T,true,Pred> svec_v1(pred); svec_v1= v1;\r
+ codeproject::sorted_vector<T,true,Pred> svec_v2(pred); svec_v2= v2;\r
+ unsigned i,j;\r
+ for(i=0;i<v1.size();i++){svec.erase(v1[i]);}\r
+ for(j=0;j<v2.size();j++){svec.insert(v2[j]);}\r
+ unsigned m;\r
+ for(m=0;m<svec_v1.size();m++){\r
+ if( svec_v2.find(svec_v1[m])!=svec_v2.end() ){\r
+ svec.erase(svec_v1[m]);\r
+ }\r
+ }\r
+//B) compute the result of the set-operation (v0+v2)-v1\r
+ codeproject::sorted_vector<T,true,Pred> svec1(v0.begin(),v0.end(),pred);\r
+ for(unsigned k=0;k<v2.size();k++){svec1.insert(v2[k]);}\r
+ for(unsigned l=0;l<v1.size();l++){svec1.erase(v1[l]);}\r
+ codeproject::sorted_vector<T,true,Pred>::size_type nSize= svec.size();\r
+ codeproject::sorted_vector<T,true,Pred>::size_type nSize1= svec1.size();\r
+//test whether results are the same\r
+ assert(svec==svec1);\r
+}\r
+\r
+\r
+codeproject::sorted_vector<int,true> \r
+BuildIntersection(std::vector<int>& v0,std::vector<int>& v1)\r
+{\r
+ codeproject::sorted_vector<int,true> svec(v0.begin(),v0.end());\r
+ codeproject::sorted_vector<int,true> svecIntersection;\r
+ for(unsigned i=0;i<v1.size();i++){\r
+ if( svec.find(v1[i])!=svec.end() ){\r
+ svecIntersection.insert(v1[i]);\r
+ }\r
+ }\r
+ return svecIntersection;\r
+}\r
+codeproject::sorted_vector<int,true> \r
+BuildIntersection1(std::vector<int>& v0,std::vector<int>& v1)\r
+{\r
+ codeproject::sorted_vector<int,true> svec(v0.begin(),v0.end());\r
+ codeproject::sorted_vector<int,true> svecIntersection;\r
+ codeproject::sorted_vector<int,true>::Cont& vInterSect= \r
+ svecIntersection.get_container();\r
+ for(unsigned i=0;i<v1.size();i++){\r
+ if( svec.find(v1[i])!=svec.end() ){\r
+ vInterSect.push_back(v1[i]);\r
+ }\r
+ }\r
+ svecIntersection.sort();\r
+ return svecIntersection;\r
+}\r
+\r
+\r
+struct ltstr\r
+{\r
+ bool operator()(const char* s1, const char* s2) const\r
+ {\r
+ return strcmp(s1, s2) < 0;\r
+ }\r
+};\r
+\r
+int SGITest()\r
+{\r
+ using namespace std;\r
+ using namespace codeproject;\r
+ const int N = 6;\r
+ const char* a[N] = {"isomer", "ephemeral", "prosaic", \r
+ "nugatory", "artichoke", "serif"};\r
+ const char* b[N] = {"flat", "this", "artichoke",\r
+ "frigate", "prosaic", "isomer"};\r
+\r
+ sorted_vector<const char*,true,ltstr> A(a, a + N);\r
+ sorted_vector<const char*,true,ltstr> B(b, b + N);\r
+ sorted_vector<const char*,true,ltstr> C;\r
+\r
+ cout << "Set A: ";\r
+ copy(A.begin(), A.end(), ostream_iterator<const char*>(cout, " "));\r
+ cout << endl;\r
+ cout << "Set B: ";\r
+ copy(B.begin(), B.end(), ostream_iterator<const char*>(cout, " ")); \r
+ cout << endl;\r
+\r
+ cout << "Union: ";\r
+ set_union(A.begin(), A.end(), B.begin(), B.end(),\r
+ ostream_iterator<const char*>(cout, " "),\r
+ ltstr()); \r
+ cout << endl;\r
+ return 0;\r
+}\r
+\r
+void TestAllSet()\r
+{\r
+ using namespace std;\r
+ using namespace codeproject;\r
+ typedef sorted_vector<const char*,true,ltstr> StrSet;\r
+ StrSet months;\r
+ months.insert("jan");\r
+ months.insert("feb");\r
+ months.insert("mar");\r
+ months.insert("apr");\r
+ months.insert("may");\r
+ months.insert("jun");\r
+ months.insert("jul");\r
+ months.insert("aug");\r
+ months.insert("sep");\r
+ months.insert("oct");\r
+ months.insert("nov");\r
+ months.insert("dec");\r
+ StrSet::iterator it= months.find("jul");\r
+ assert(strcmp(*it,"jul")==0);\r
+ cout << "previous of jul (in alphabetical order) is " << (it[-1]) << endl;\r
+ cout << "next of jul (in alphabetical order) is " << (it[1]) << endl;\r
+\r
+ cout << "months in alphabetical order: " << endl;\r
+ copy(months.begin(),months.end(),ostream_iterator<const char*>(cout," ")); \r
+ cout << endl << "months in reverse alphabetical order: " << endl;\r
+ copy(months.rbegin(),months.rend(),ostream_iterator<const char*>(cout," "));\r
+ /*test count*/\r
+ {\r
+ for(StrSet::iterator it= months.begin();it!=months.end();++it){\r
+ assert(months.count(*it)==1);\r
+ }\r
+ }\r
+ /*test copy construction and comparison operators*/\r
+ StrSet monthsCopy(months);\r
+ assert( months==monthsCopy \r
+ && months<=monthsCopy && months>=monthsCopy\r
+ && !(months<monthsCopy) && !(months>monthsCopy));\r
+\r
+ std::pair<StrSet::iterator,StrSet::iterator> pairMismatch=\r
+ mismatch(months.begin(),months.end(),monthsCopy.begin());\r
+ assert(pairMismatch.first==months.end() && pairMismatch.second==monthsCopy.end());\r
+\r
+ /*test insertion of already present element*/\r
+ copy(months.begin(),months.end(),inserter(monthsCopy,monthsCopy.begin()));\r
+ assert(months.size()==monthsCopy.size());\r
+\r
+ /*test insert member functions*/\r
+ months.insert(monthsCopy.begin(),monthsCopy.end());\r
+ assert(months==monthsCopy);\r
+ StrSet months1(months.begin(),months.begin()+3);\r
+ months1.insert(months.begin()+1,months.end());\r
+ assert(months1==months);\r
+ months1.insert("aug");\r
+ months1.insert("xxx");\r
+ months1.insert(months1.find("xxx"),"yyy");\r
+ months1.insert("zzz");\r
+ assert(months1>months && months1.size()==months.size()+3);\r
+ /*test erase member functions*/\r
+ months1.erase(months1.find("xxx"),months1.end());\r
+ assert(months1.size()==months.size());\r
+\r
+ /*test lower_bound,upper_bound,equal_range*/\r
+ assert( strcmp(*months.lower_bound("jul"),"jul")==0);\r
+ \r
+\r
+ cout << endl;\r
+}\r
+\r
+\r
+int main()\r
+{\r
+//timed tests\r
+ std::vector<int> v;\r
+ int i;\r
+ for(i=0;i<50000;i++){v.push_back(rand());}\r
+ std::cout << "--------------Tests with element type int-------------" << std::endl;\r
+ ExecTests(v);\r
+ \r
+ std::vector<STest> vt;\r
+ for(i=0;i<50000;i++){vt.push_back(MakeSTest());}\r
+ std::cout << "-Tests with element type 'STest' (string,int)--------" << std::endl;\r
+ ExecTests(v);\r
+\r
+//set operations-test\r
+ std::vector<int> v1,v2;\r
+ for(i=0;i<10000;i++){v1.push_back(rand());}\r
+ for(i=0;i<10000;i++){v2.push_back(rand());}\r
+ TestSetOperations(v,v1,v2,std::greater<int>());\r
+\r
+ assert(BuildIntersection(v1,v2)==BuildIntersection1(v1,v2));\r
+ SGITest();\r
+ TestAllSet();\r
+ return 0;\r
+}
\ No newline at end of file
--- /dev/null
+# Microsoft Developer Studio Project File - Name="sorted_vector" - Package Owner=<4>\r
+# Microsoft Developer Studio Generated Build File, Format Version 6.00\r
+# ** DO NOT EDIT **\r
+\r
+# TARGTYPE "Win32 (x86) Console Application" 0x0103\r
+\r
+CFG=sorted_vector - Win32 Debug\r
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,\r
+!MESSAGE use the Export Makefile command and run\r
+!MESSAGE \r
+!MESSAGE NMAKE /f "sorted_vector.mak".\r
+!MESSAGE \r
+!MESSAGE You can specify a configuration when running NMAKE\r
+!MESSAGE by defining the macro CFG on the command line. For example:\r
+!MESSAGE \r
+!MESSAGE NMAKE /f "sorted_vector.mak" CFG="sorted_vector - Win32 Debug"\r
+!MESSAGE \r
+!MESSAGE Possible choices for configuration are:\r
+!MESSAGE \r
+!MESSAGE "sorted_vector - Win32 Release" (based on "Win32 (x86) Console Application")\r
+!MESSAGE "sorted_vector - Win32 Debug" (based on "Win32 (x86) Console Application")\r
+!MESSAGE \r
+\r
+# Begin Project\r
+# PROP AllowPerConfigDependencies 0\r
+# PROP Scc_ProjName ""\r
+# PROP Scc_LocalPath ""\r
+CPP=cl.exe\r
+RSC=rc.exe\r
+\r
+!IF "$(CFG)" == "sorted_vector - Win32 Release"\r
+\r
+# PROP BASE Use_MFC 0\r
+# PROP BASE Use_Debug_Libraries 0\r
+# PROP BASE Output_Dir "Release"\r
+# PROP BASE Intermediate_Dir "Release"\r
+# PROP BASE Target_Dir ""\r
+# PROP Use_MFC 0\r
+# PROP Use_Debug_Libraries 0\r
+# PROP Output_Dir "Release"\r
+# PROP Intermediate_Dir "Release"\r
+# PROP Target_Dir ""\r
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c\r
+# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c\r
+# ADD BASE RSC /l 0x807 /d "NDEBUG"\r
+# ADD RSC /l 0x807 /d "NDEBUG"\r
+BSC32=bscmake.exe\r
+# ADD BASE BSC32 /nologo\r
+# ADD BSC32 /nologo\r
+LINK32=link.exe\r
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386\r
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386\r
+\r
+!ELSEIF "$(CFG)" == "sorted_vector - Win32 Debug"\r
+\r
+# PROP BASE Use_MFC 0\r
+# PROP BASE Use_Debug_Libraries 1\r
+# PROP BASE Output_Dir "Debug"\r
+# PROP BASE Intermediate_Dir "Debug"\r
+# PROP BASE Target_Dir ""\r
+# PROP Use_MFC 0\r
+# PROP Use_Debug_Libraries 1\r
+# PROP Output_Dir "Debug"\r
+# PROP Intermediate_Dir "Debug"\r
+# PROP Target_Dir ""\r
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c\r
+# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c\r
+# ADD BASE RSC /l 0x807 /d "_DEBUG"\r
+# ADD RSC /l 0x807 /d "_DEBUG"\r
+BSC32=bscmake.exe\r
+# ADD BASE BSC32 /nologo\r
+# ADD BSC32 /nologo\r
+LINK32=link.exe\r
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept\r
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept\r
+\r
+!ENDIF \r
+\r
+# Begin Target\r
+\r
+# Name "sorted_vector - Win32 Release"\r
+# Name "sorted_vector - Win32 Debug"\r
+# Begin Group "Source Files"\r
+\r
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"\r
+# Begin Source File\r
+\r
+SOURCE=.\main.cpp\r
+# End Source File\r
+# End Group\r
+# Begin Group "Header Files"\r
+\r
+# PROP Default_Filter "h;hpp;hxx;hm;inl"\r
+# Begin Source File\r
+\r
+SOURCE=.\sorted_vector.h\r
+# End Source File\r
+# End Group\r
+# Begin Group "Resource Files"\r
+\r
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"\r
+# End Group\r
+# End Target\r
+# End Project\r
--- /dev/null
+/* STL-conforming "sorted vector" container\r
+ *\r
+ * (C) 2002 Martin Holzherr (holzherr@infobrain.com). All rights reserved.\r
+ *\r
+ * Permission is granted to use, distribute and modify this code provided that:\r
+ * · this copyright notice appears,\r
+ * · \r
+ * The author welcomes any suggestions on the code or reportings of actual\r
+ * use of the code. Please send your comments to holzherr@infobrain.com.\r
+ *\r
+ * The author makes NO WARRANTY or representation, either express or implied,\r
+ * with respect to this code, its quality, accuracy, merchantability, or\r
+ * fitness for a particular purpose. This software is provided "AS IS", and\r
+ * you, its user, assume the entire risk as to its quality and accuracy.\r
+ *\r
+ * Created: November 19th, 2002\r
+ * Last modified: November 27th, 2002 \r
+ (changed namespace from std to codeproject;\r
+ uses template member functions for MSCVER>=1300)\r
+ \r
+ */\r
+\r
+#ifndef SORTED_VECTOR_\r
+#define SORTED_VECTOR_\r
+#define VERSION_SORTED_VECTOR_ 0x00010010\r
+\r
+\r
+#include <algorithm>\r
+#include <vector>\r
+#include <utility>\r
+#include <functional>\r
+\r
+#pragma pack(push,8)\r
+#pragma warning(push,3)\r
+\r
+\r
+namespace codeproject{\r
+ // TEMPLATE CLASS sorted_vector\r
+\r
+ template<class K, bool bNoDuplicates= false,class Pr = std::less<K>, class A = std::allocator<K> >\r
+ class sorted_vector {\r
+public:\r
+ typedef sorted_vector<K,bNoDuplicates,Pr,A> Myt_;\r
+ typedef std::vector<K,A> Cont;\r
+ typedef Cont::allocator_type allocator_type;\r
+ typedef Cont::size_type size_type;\r
+ typedef Cont::difference_type difference_type;\r
+ typedef Cont::reference reference;\r
+ typedef Cont::const_reference const_reference;\r
+ typedef Cont::value_type value_type;\r
+ typedef K key_type;\r
+ typedef Cont::iterator iterator;\r
+ typedef Cont::const_iterator const_iterator;\r
+ typedef Pr key_compare;\r
+ typedef Pr value_compare;\r
+\r
+ typedef Cont::const_reverse_iterator\r
+ const_reverse_iterator;\r
+ typedef Cont::reverse_iterator reverse_iterator;\r
+\r
+ typedef std::pair<iterator, iterator> Pairii_;\r
+ typedef std::pair<const_iterator, const_iterator> Paircc_;\r
+ typedef std::pair<iterator, bool> Pairib_;\r
+ explicit sorted_vector(const Pr& pred = Pr(),const A& al = A())\r
+ :key_compare_(pred),vec_(al){}\r
+#if (_MSC_VER >= 1300)\r
+ template<class It>\r
+ sorted_vector(It first, It beyond, \r
+ const Pr& pred = Pr(),const A& al = A())\r
+ :key_compare_(pred),vec_(first,beyond,al)\r
+ {stable_sort();}\r
+#else\r
+ sorted_vector(const_iterator first, const_iterator beyond, \r
+ const Pr& pred = Pr(),const A& al = A())\r
+ :key_compare_(pred),vec_(first,beyond,al)\r
+ {stable_sort();}\r
+#endif\r
+ sorted_vector(const Myt_& x)\r
+ : vec_(x.vec_),key_compare_(x.key_compare_)\r
+ {}\r
+ ~sorted_vector() {}\r
+ Myt_& operator=(const Myt_& x) {vec_.operator=(x.vec_);\r
+ key_compare_= x.key_compare_;\r
+ return *this;}\r
+ Myt_& operator=(const Cont& x){vec_.operator=(x);\r
+ sort();return *this;}\r
+ \r
+ void reserve(size_type n) {vec_.reserve(n);}\r
+ iterator begin() {return vec_.begin(); }\r
+ const_iterator begin() const {return vec_.begin(); }\r
+ iterator end() {return vec_.end();}\r
+ const_iterator end() const {return vec_.end();}\r
+ reverse_iterator rbegin() {return vec_.rbegin();}\r
+ const_reverse_iterator rbegin() const \r
+ {return vec_.rbegin();}\r
+\r
+ reverse_iterator rend() {return vec_.rend();}\r
+ const_reverse_iterator rend() const \r
+ {return vec_.rend();}\r
+\r
+\r
+ size_type size() const {return vec_.size();}\r
+ size_type max_size() const {return vec_.max_size();}\r
+ bool empty() const {return vec_.empty();}\r
+ A get_allocator() const {return vec_.get_allocator();}\r
+ const_reference at(size_type p) const {return vec_.at(p);}\r
+ reference at(size_type p) {return vec_.at(p);}\r
+ const_reference operator[](size_type p) const\r
+ {return vec_.operator[](p);}\r
+ \r
+ reference operator[](size_type p) {return vec_.operator[](p);}\r
+ reference front() {return vec_.front();}\r
+ const_reference front() const {return vec_.front();}\r
+ reference back() {return vec_.back();}\r
+ const_reference back() const {return vec_.back();}\r
+ void pop_back() {vec_.pop_back();}\r
+\r
+ void assign(const_iterator first, const_iterator beyond) \r
+ {vec_.assign(first,beyond);}\r
+ void assign(size_type n, const K& x = K())\r
+ {vec_.assign(n,x);}\r
+/*insert members*/\r
+ Pairib_ insert(const value_type& x)\r
+ {\r
+ if(bNoDuplicates){\r
+ iterator p= lower_bound(x);\r
+ if(p==end()||key_compare_(x,*p)){\r
+ return Pairib_(InsertImpl_(p,x),true);\r
+ }else{\r
+ return Pairib_(p,false);\r
+ }\r
+ }else{\r
+ iterator p= upper_bound(x);\r
+ return Pairib_(InsertImpl_(p,x),true);\r
+ }\r
+ }\r
+ iterator insert(iterator it, const value_type& x)//it is the hint\r
+ {\r
+ if(it!=end() ){\r
+ if(bNoDuplicates){\r
+ if(key_compare_(*it,x)){\r
+ if((it+1)==end()||KeyCompare_Gt_(*(it+1),x)){//use hint\r
+ return InsertImpl_(it+1,x);\r
+ }else if(KeyCompare_Geq_(*(it+1),x)){\r
+ return end();\r
+ }\r
+ }\r
+ }else{\r
+ if( KeyCompare_Leq_(*it,x)\r
+ &&((it+1)==end()||KeyCompare_Geq_(*(it+1),x))){\r
+ return InsertImpl_(it+1,x);\r
+ }\r
+ }\r
+ }\r
+ return insert(x).first;\r
+ }\r
+#if (_MSC_VER >= 1300)\r
+ template<class It>\r
+ void insert(It first, It beyond)\r
+ {\r
+ size_type n= std::distance(first,beyond);\r
+ reserve(size()+n);\r
+ for( ;first!=beyond;++first){\r
+ insert(*first);\r
+ }\r
+ }\r
+#else\r
+ void insert(const_iterator first, const_iterator beyond)\r
+ {\r
+ size_type n= std::distance(first,beyond);\r
+ reserve(size()+n);\r
+ for( ;first!=beyond;++first){\r
+ insert(*first);\r
+ }\r
+ }\r
+#endif\r
+ iterator erase(iterator p) {return vec_.erase(p);}\r
+ iterator erase(iterator first, iterator beyond)\r
+ {return vec_.erase(first,beyond);}\r
+ size_type erase(const K& key) \r
+ {\r
+ Pairii_ begEnd= equal_range(key);\r
+ size_type n= std::distance(begEnd.first,begEnd.second);\r
+ erase(begEnd.first,begEnd.second);\r
+ return n;\r
+ }\r
+ void clear() {return vec_.clear();}\r
+ \r
+ bool Eq_(const Myt_& x) const \r
+ {return (size() == x.size()\r
+ && std::equal(begin(), end(), x.begin())); }\r
+ bool Lt_(const Myt_& x) const\r
+ {return (std::lexicographical_compare(begin(), end(),\r
+ x.begin(), x.end()));}\r
+ void swap(Myt_& x)\r
+ {vec_.swap(x.vec_);std::swap(key_compare_,x.key_compare_);}\r
+ \r
+ friend void swap(Myt_& x, Myt_& Y_)\r
+ {x.swap(Y_); }\r
+\r
+ key_compare key_comp() const {return key_compare_; }\r
+ value_compare value_comp() const {return (key_comp()); }\r
+ iterator find(const K& k)\r
+ { iterator p = lower_bound(k);\r
+ return (p==end()||key_compare_(k, *p))? end():p;\r
+ }\r
+ const_iterator find(const K& k) const\r
+ {const_iterator p = lower_bound(k);\r
+ return (p==end()||key_compare_(k,*p))?end():p;}\r
+ size_type count(const K& k) const\r
+ {Paircc_ Ans_ = equal_range(k);\r
+ size_type n = std::distance(Ans_.first, Ans_.second);\r
+ return (n); }\r
+ iterator lower_bound(const K& k)\r
+ {return std::lower_bound(begin(), end(), k, key_compare_); }\r
+ const_iterator lower_bound(const K& k) const\r
+ {return std::lower_bound(begin(), end(), k, key_compare_); }\r
+ iterator upper_bound(const K& k)\r
+ {return std::upper_bound(begin(), end(), k, key_compare_); }\r
+ const_iterator upper_bound(const K& k) const\r
+ {return std::upper_bound(begin(), end(), k, key_compare_); }\r
+ Pairii_ equal_range(const K& k)\r
+ {return std::equal_range(begin(), end(), k, key_compare_); }\r
+ Paircc_ equal_range(const K& k) const\r
+ {return std::equal_range(begin(), end(), k, key_compare_); }\r
+\r
+/*functions for use with direct std::vector-access*/\r
+ Cont& get_container()\r
+ {return vec_;}\r
+ void sort()//restore sorted order after low level access \r
+ { std::sort(vec_.begin(),vec_.end(),key_compare_);\r
+ if( bNoDuplicates ){\r
+ vec_.erase(Unique_(),vec_.end());\r
+ }\r
+ }\r
+ void stable_sort()//restore sorted order after low level access \r
+ { std::stable_sort(vec_.begin(),vec_.end(),key_compare_);\r
+ if( bNoDuplicates ){\r
+ erase(Unique_(),end());\r
+ }\r
+ } \r
+protected:\r
+ iterator Unique_()\r
+ { iterator front_= vec_.begin(),out_= vec_.end(),end_=vec_.end();\r
+ bool bCopy_= false;\r
+ for(iterator prev_; (prev_=front_)!=end_ && ++front_!=end_; ){\r
+ if( key_compare_(*prev_,*front_)){\r
+ if(bCopy_){\r
+ *out_= *front_;\r
+ out_++;\r
+ }\r
+ }else{\r
+ if(!bCopy_){out_=front_;bCopy_=true;}\r
+ }\r
+ }\r
+ return out_;\r
+ }\r
+ iterator InsertImpl_(iterator p,const value_type& x)\r
+ {return vec_.insert(p,x);}\r
+ bool KeyCompare_Leq_(const K& ty0,const K& ty1)\r
+ {return !key_compare_(ty1,ty0);}\r
+ bool KeyCompare_Geq_(const K& ty0,const K& ty1)\r
+ {return !key_compare_(ty0,ty1);}\r
+ bool KeyCompare_Gt_(const K& ty0,const K& ty1)\r
+ {return key_compare_(ty1,ty0);}\r
+\r
+ key_compare key_compare_;\r
+ Cont vec_;\r
+};\r
+\r
+\r
+template<class K,bool bNoDuplicates,class Pr, class A> inline\r
+ bool operator==(const sorted_vector<K, bNoDuplicates,Pr,A>& x,\r
+ const sorted_vector<K, bNoDuplicates,Pr,A>& Y_)\r
+ {return x.Eq_(Y_); }\r
+template<class K,bool bNoDuplicates,class Pr, class A> inline\r
+ bool operator!=(const sorted_vector<K, bNoDuplicates,Pr,A>& x,\r
+ const sorted_vector<K, bNoDuplicates,Pr,A>& Y_)\r
+ {return !(x == Y_); }\r
+template<class K,bool bNoDuplicates,class Pr, class A> inline\r
+ bool operator<(const sorted_vector<K, bNoDuplicates,Pr,A>& x,\r
+ const sorted_vector<K, bNoDuplicates,Pr,A>& Y_)\r
+ {return x.Lt_(Y_);}\r
+template<class K,bool bNoDuplicates,class Pr,class A> inline\r
+ bool operator>(const sorted_vector<K, bNoDuplicates,Pr,A>& x,\r
+ const sorted_vector<K, bNoDuplicates,Pr,A>& Y_)\r
+ {return Y_ < x; }\r
+template<class K,bool bNoDuplicates,class Pr, class A> inline\r
+ bool operator<=(const sorted_vector<K, bNoDuplicates,Pr,A>& x,\r
+ const sorted_vector<K, bNoDuplicates,Pr,A>& Y_)\r
+ {return !(Y_ < x); }\r
+template<class K, bool bNoDuplicates,class Pr,class A> inline\r
+ bool operator>=(const sorted_vector<K, bNoDuplicates,Pr,A>& x,\r
+ const sorted_vector<K, bNoDuplicates,Pr,A>& Y_)\r
+ {return (!(x < Y_)); }\r
+}\r
+#pragma warning(pop)\r
+#pragma pack(pop)\r
+#elif VERSION_SORTED_VECTOR_ != 0x00010010\r
+#error You have included two sorted_vector.h with different version numbers\r
+#endif\r
--- /dev/null
+<!DOCTYPE HTML>\r
+\r
+\r
+<html>\r
+<head>\r
+ <title>An STL compliant sorted vector - CodeProject</title> \r
+ <link type="text/css" rel="stylesheet" href="//dj9okeyxktdvd.cloudfront.net/App_Themes/CodeProject/Css/Main.min.css?dt=2.8.140814.1">\r
+<link type="text/css" rel="stylesheet" href="//dj9okeyxktdvd.cloudfront.net/App_Themes/CodeProject/Css/print.min.css?dt=2.8.140814.1">\r
+\r
+ \r
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />\r
+<meta name="Description" content="A template container which implements set/multiset functionality using a vector; Author: Martin Holzherr; Updated: 29 Nov 2002; Section: STL; Chapter: Platforms, Frameworks & Libraries; Updated: 29 Nov 2002" />\r
+<meta name="Keywords" content="C++, Windows, Visual-Studio, STL, Dev, Intermediate,STL,Platforms, Frameworks & Libraries,Free source code, tutorials" />\r
+<meta name="Author" content="Martin Holzherr" />\r
+<meta name="Rating" content="General" />\r
+<meta name="Robots" content="index, follow, NOODP" />\r
+<meta name="Revisit-After" content="1 days" />\r
+<meta name="application-name" content="CodeProject" />\r
+\r
+<link rel="dns-prefetch" href="//ajax.googleapis.com" /> \r
+<link rel="canonical" href="/Articles/3217/An-STL-compliant-sorted-vector" />\r
+\r
+\r
+<link rel="alternate" type="application/rss+xml" title="CodeProject Latest articles - All Topics" href="http://www.codeproject.com/WebServices/ArticleRSS.aspx?cat=1" />
+<link rel="alternate" type="application/rss+xml" title="CodeProject Latest articles - Android" href="http://www.codeproject.com/WebServices/ArticleRSS.aspx?cat=22" />
+<link rel="alternate" type="application/rss+xml" title="CodeProject Latest articles - iOS" href="http://www.codeproject.com/WebServices/ArticleRSS.aspx?cat=25" />
+<link rel="alternate" type="application/rss+xml" title="CodeProject Latest articles - C++" href="http://www.codeproject.com/WebServices/ArticleRSS.aspx?cat=2" />
+<link rel="alternate" type="application/rss+xml" title="CodeProject Latest articles - C#" href="http://www.codeproject.com/WebServices/ArticleRSS.aspx?cat=3" />
+<link rel="alternate" type="application/rss+xml" title="CodeProject Latest articles - Web" href="http://www.codeproject.com/WebServices/ArticleRSS.aspx?cat=23" />
+<link rel="alternate" type="application/rss+xml" title="CodeProject Lounge Postings" href="http://www.codeproject.com/webservices/LoungeRSS.aspx" />\r
+<link rel="search" type="application/opensearchdescription+xml" title="CodeProject" href="http://www.codeproject.com/info/OpenSearch.xml" />\r
+\r
+ <base target="_top" />\r
+ <link rel="icon" href="/favicon.ico" type="image/ico" >
+<link rel="shortcut icon" href="/favicon.ico" type="image/ico" >
+<link rel="apple-touch-icon" href="/images/FavIcon-Apple.png" type="image/png" >
+<script type="text/javascript" language="Javascript">//<![CDATA[\r
+function defrm () { /* thanks twitter */ document.write = ''; window.top.location = window.self.location; setTimeout(function() { document.body.innerHTML = ''; }, 0); window.self.onload = function(evt) { document.body.innerHTML = ''; }; }if (window.top !== window.self) { try { if (window.top.location.host) { /* will throw */ } else { defrm(); /* chrome */ } } catch (ex) { defrm(); /* everyone else */ } }if (typeof(DemoUrl)!='undefined') document.write(unescape('%3Cme')+'ta http'+'-equiv="re'+'fresh" con'+'tent="1;url='+DemoUrl+unescape('"%3CE'));\r
+\r
+//]]>\r
+</script>\r
+\r
+ \r
+\r
+\r
+\r
+\r
+<script type="text/javascript">\r
+ var _gaq = _gaq || [];\r
+ _gaq.push(['_setAccount', 'UA-1735123-1']);\r
+ _gaq.push(['_trackPageview']);\r
+ _gaq.push(['_setDomainName', 'www.codeproject.com']);\r
+ _gaq.push(['_setSessionTimeout', '1200']); \r
+\r
+ (function () {\r
+ var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;\r
+ ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';\r
+ (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(ga);\r
+ })(); \r
+</script>\r
+\r
+\r
+</head> \r
+\r
+<body class="unknown unknown0">\r
+\r
+<a class="access-link" href="#Main"><img alt="Click here to Skip to main content" src="//dj9okeyxktdvd.cloudfront.net/Images/t.gif" /></a>\r
+\r
+\r
+\r
+\r
+\r
+<div class="page-background">\r
+\r
+ \r
+ \r
+\r
+ \r
+\r
+ <table id="ctl00_Bn" style="width:100%;height:135px" cellpadding="0" cellspacing="0" class="banner fluid">\r
+ <tr valign="bottom">\r
+ <td class="blank-background" style="height:31px"> </td>\r
+ <td class="blank-background" rowspan="3" style="width:250px;height:135px"><a href="/"><img id="ctl00_Logo" tabindex="1" title="CodeProject" src="//dj9okeyxktdvd.cloudfront.net/App_Themes/CodeProject/Img/logo250x135.gif" alt="Home" height="135" width="250" border="0" /></a></td>\r
+ <td class="blank-background align-right" style="width:728px;height:31px"></td>\r
+ <td class="blank-background" style="height:31px"> </td>\r
+ </tr>\r
+ <tr valign="middle">\r
+ <td class="theme1-background" style="height:94px"> </td>\r
+ <td class="theme1-background ad"></td>\r
+ <td class="theme1-background" style="height:94px"> </td>\r
+ </tr>\r
+ <tr valign="top">\r
+ <td style="height: 14px;"></td>\r
+ <td style="height: 14px;" class="blank-background"></td>\r
+ <td style="height: 14px;"></td>\r
+ </tr>\r
+</table>\r
+\r
+\r
+ <a href="#Main"><img alt="Click here to Skip to main content" class="access-link" src="//dj9okeyxktdvd.cloudfront.net/Images/t.gif" /></a>\r
+\r
+ \r
+ \r
+ \r
+\r
+ <div id="A" class="container-content-wrap fluid print"> \r
+\r
+ <div itemscope itemtype="http://schema.org/Article" class="container-content"> \r
+\r
+ <div class="clearfix">\r
+ <div class="float-left container-breadcrumb">\r
+ <div><a href="/script/Content/SiteMap.aspx">Articles</a> » <a href="/Chapters/8/Platforms-Frameworks-Libraries.aspx">Platforms, Frameworks & Libraries</a> » <a href="/KB/stl/"><span itemprop="articleSection">STL</span></a> » <a href="/KB/stl/#Collections+and+Iterators">Collections and Iterators</a></div>\r
+ </div>\r
+\r
+ <div class="align-left float-right padded-top" style="width">\r
+ \r
+ </div>\r
+\r
+ <div class="float-right article-nav">\r
+ \r
+ \r
+ </div>\r
+\r
+ <div class="align-right float-left">\r
+ \r
+ </div>\r
+ </div>\r
+\r
+ <table class="extended container-article-parts" cellpadding="0" cellspacing="0">\r
+ <tr valign="top">\r
+ <td width="117px">\r
+\r
+ \r
+\r
+ </td>\r
+ <td>\r
+ \r
+ <div id="AT" class="container-article fluid tight"> \r
+ <div class="article">\r
+\r
+ <form name="aspnetForm" method="post" action="/Articles/3217/An-STL-compliant-sorted-vector?display=Print" id="aspnetForm" style="margin:0;padding:0">\r
+<input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="l4t1EWStXXSrscUFnHs1oTVsO7YMMzAtJDm0EFSmuE82rBXzQZkPU/sQy8UTLNd+jZyZjwaJq0+1UGZ96xx9ZnpUl9uPw6F8x2xGemBcOQQ1poJ0dxSgo+uftqfQg2Lyf+UIsvviIugxYvTWjhIjx5LzyUce4oyNrJqDy26gInV4Z1lElc+ZpT96CbMOb9YObEAIb5B/spytqhmrONMjfROSuMW6PtARYRU5F31DKhdDdm7m97R+q5gJ/ow3vkWjZbj1UOYP/wEopc/YY/MOdyAQip5Ml8uhRMnZAzrS6r4H4AE5nn+Io/rgtePyF6wAgl3gN+3l8tm9KVVGVFuzmGoiQ7qJhzzYgoZowODS76zUpQnqkHuysqaJ6FkQWOxDg8g95p3XHX5jta3MCeltfcfpz0ReoHYJF2fagTXLUZ0ktLjIZouS/qtcSb/dE/6/X8yUsda267qw0r9NHD6VwHd7rwbUi0ydBZVmYfVPqAkCJFZMqwMYy7N2IR+4ukIrcoBH5lZfpPhCymHElhlpKIvjlIdEFRXouBz1CxQJb97SxkLQtFMWrglDOnSYXLUucQPEQdKMf74+CWz8Fsv9n3cmcsS12vaYc81AboaY8XOaezn3cBFh1zGhrav4JXF29cl/qBBXJe19konYBf67DyFl0EQJJLexfSEPTmGRXekr1byrotc7s2lH6GFLFeoYVrgCqKd9Dk0vgcSQkDgV6ZLT27HVgeXuU6HfyL3d1UHoppkNMYdTqRazkxfOc8Tc0UWih7e0JTQhfqgDFWmPczWpkd/UmqOLsJeOddvvsUN0K6KzGA+LFx8istHkiooDTYct4xuKAF6WUD3dDKaM252NCiJsylNlNty+uec+aB+Wge/KDr4zuQKZwm6GhORVXR8hK3RlRjPxCQL4/KnESLyCVx41AU/Be3uBV3MDBfvID/RZB/XqN8lzeAdaKXY3ksWFbG8IntTQcadN3i7lC1aM5GhN6cOBXQurIEiT4x8hdIbwqnjap+Y6u+l9JIFUTx0aq90BVuopQ/sP7JhyL0IJoZkk2grdWO8nzG/0E+heBqO/6NnkmbGJ9bKlAXLHYgRV1OJAYCg2/eAgwgOX071XY5h/eR7d95+Hj3hc6nT2CPdSB02KeP86bQlXJ0p+jyqVOhTvIGKFq+KzS8UQ+ug6P7PDZ9Z0+37KxeMRXY0avj72l44j1oQvk4DmuxgNLaQg9zrGLqi3nbGlhoTxA6qJGwn92oCVb1NfbO+U+xTubKEG/L3s4lTIiDXOZvtKntpH6EOiu62zb3CM6qLqnQkexexmW0vaBd6Pb5I1FIBcsuRzf7Gah8/+RhjgNWzosElbBD3znV9AdUguuueIktTS5dMA9qmCqdH7LdF2qWBYftx0oHumT7u9vq1tUj5dA7YqwxWMHt3j1nFwW2EQPfOLLsFzknCvtORyRJUbR+GxTPdZKtJrIyS21f1qoaszeLFdyONpscW+hiRMbWtuWI/VHFfwway/1qB/xDkUh42VlWin2GykpgwEiO8y12Hr1PzEp1+rHA5q9NfXAWKSvib0ECX6JblNBBlXAYmgA3KKlHNWeAUxqE8JUeJ613P8gZwbI7oC5csabeU/ZkHlU0TL4pHJyrng5KLJmKbmb4/sUBMt86Oqbw8TTE0IeNrXBY1xoZQ6fm2hfzvnEGxFITas30GWt4+0x29qhTIhseeFt5iL9JkDTu38i3vPf+UiisLAMJwnZ5A3DBEMQgAe19LgJr/M78YTndDl6lhaktlDfbpaxyGma7uVIlb1FwZ88OCKdp74W9ZTB/y/HDLU4CjU8D84gYO6YLQb1AM9Q2s1jwNRwXkZBP8Q+7xVyYoOhhGKj/7LLFow1oqH3bEUd802LPtTMCrNC0pwu3CJexR6rqcq1d6R4OKTRjSGiDnxDVX3sfldRXkhH+Zi+oNi1Pmx9d9r8YocjEYygzLXoeglAflR0lGe5wkl+Oi3vtJBDtKOezC9trDU39qpSS0HDA/hCErJ2AiBcWWQ895tfFgk7xEgxehYyM3tid6aWSkYdeeWCxNMUDzz0kKjA15W7LFvFRvBubT+FJ7Qf5gBniUNQQjG1h+y0JaLkMKtPmoJMfcl8Q==" />\r
+\r
+\r
+ \r
+ \r
+ <div class="header">\r
+ <a name="Main"></a>\r
+\r
+ \r
+ <a name="_articleTop" id="_articleTop"></a>\r
+ <div class="title">\r
+ \r
+ <h1 id="ctl00_ArticleTitle" itemprop="name">An STL compliant sorted vector</h1> \r
+ </div>\r
+\r
+ <div style="height:34px">\r
+ \r
+ <div class="entry float-left">\r
+ \r
+ <div class="float-left">\r
+\r
+ <span class="author"><a href="/script/Membership/View.aspx?mid=6888" rel="author"><span itemprop="author" itemscope itemtype="http://schema.org/Person"><span itemprop="name">Martin Holzherr</span></span></a></span>, \r
+ <span class="date" itemprop="dateModified" content="2002-11-29 00:00:00">\r
+ 28 Nov 2002</span>\r
+ \r
+ <div id="ctl00_CurRat" class="tooltip anchorLink" style="cursor:pointer;margin-top: 5px">\r
+ \r
+ \r
+\r
+<table cellpadding="0" cellspacing="0" class="small-text" itemprop="aggregateRating" itemscope itemtype="http://schema.org/AggregateRating"> \r
+<tr>\r
+ \r
+ <td class="nowrap">\r
+\r
+ \r
+ <meta itemprop="bestRating" content="5"> \r
+ <meta itemprop="worstRating" content="1">\r
+ \r
+\r
+ <span id="ctl00_ArticleRating_VI">\r
+ <div class="nowrap rating-stars-large" style="position:relative;">\r
+ <div class="clipped align-left float-left">\r
+ <img src="//dj9okeyxktdvd.cloudfront.net/script/Ratings/Images/stars-fill-lg.png" border="0" />\r
+ </div><div class="clipped" style="position:relative;">\r
+ <img src="//dj9okeyxktdvd.cloudfront.net/script/Ratings/Images/stars-empty-lg.png" border="0" style="position:absolute;top:0;right:0;" />\r
+ </div>\r
+</div>\r
+ </span>\r
+\r
+ \r
+ </td>\r
+ \r
+ <td id="ctl00_ArticleRating_VR" class="nowrap">\r
+ \r
+ <span id="ctl00_ArticleRating_VotesR"> <span itemprop="ratingValue" class="rating">4.56</span> (<span itemprop="ratingCount" class="count">13</span> votes)</span>\r
+ \r
+ </td>\r
+\r
+</tr>\r
+\r
+</table>\r
+\r
+\r
+ <div id="ctl00_RB" class="speech-bubble-container-up">\r
+ <div class="speech-bubble-up" style="width:150px !important">\r
+ \r
+<div>\r
+<table class="feature" width="100%" height="20px" title="Voting Distribution. Recent data only" cellpadding="0" cellspacing="0"><tr class="chart-row"><td class="chart-column"><img src="//dj9okeyxktdvd.cloudfront.net/Images/t.gif" width="20pxpx" height="1px" border="0px" alt="" title="" /><br /><span title="0 votes">1</span></td>\r
+<td class="chart-column"><img src="//dj9okeyxktdvd.cloudfront.net/Images/t.gif" width="20pxpx" height="1px" border="0px" alt="" title="" /><br /><span title="0 votes">2</span></td>\r
+<td class="chart-column"><img src="//dj9okeyxktdvd.cloudfront.net/script/Ratings/Images/pollcol.gif" width="20pxpx" height="2px" border="0px" alt="1 vote, 10.0%" title="1 vote, 10.0%" /><br /><span title="1 vote">3</span></td>\r
+<td class="chart-column"><img src="//dj9okeyxktdvd.cloudfront.net/script/Ratings/Images/pollcol.gif" width="20pxpx" height="5px" border="0px" alt="2 votes, 20.0%" title="2 votes, 20.0%" /><br /><span title="2 votes">4</span></td>\r
+<td class="chart-column"><img src="//dj9okeyxktdvd.cloudfront.net/script/Ratings/Images/pollcol.gif" width="20pxpx" height="20px" border="0px" alt="7 votes, 70.0%" title="7 votes, 70.0%" /><br /><span title="7 votes">5</span></td>\r
+</tr></table><div class="small-text align-center">4.56/5 - 13 votes</div><div class="small-text align-center subdue">μ 4.56, σ<sub>a</sub> 1.22 [<a href="/KB/FAQs/RatingReputationFAQ.aspx#noisefilter">?</a>]</div>\r
+</div>\r
+ </div>\r
+ <div class="speech-bubble-pointer-up">\r
+ <div class="speech-bubble-pointer-up-inner"></div>\r
+ </div>\r
+ </div>\r
+ </div>\r
+ </div>\r
+ </div>\r
+\r
+ \r
+ \r
+ \r
+\r
+ \r
+ <div class="float-right" style="margin-right:10px">\r
+ \r
+ </div> \r
+ \r
+ </div>\r
+\r
+ \r
+ <div id="ctl00_description" class="summary">A template container which implements set/multiset functionality using a vector</div> \r
+\r
+ </div>\r
+ \r
+ \r
+ \r
+\r
+\r
+ \r
+ \r
+\r
+ \r
+ \r
+ \r
+\r
+ \r
+ \r
+\r
+ \r
+\r
+ \r
+ <div id="contentdiv" class="text" itemprop="articleBody">\r
+ \r
+\r
+\r
+\r
+<ul class="download">\r
+<li><a href="/KB/stl/sorted_vector/sorted_vector_src.zip">Download source files - 7 Kb</a></li>\r
+</ul>\r
+\r
+\r
+<h2>Introduction</h2>\r
+\r
+<p><code>sorted_vector</code> adapts a <code>std::vector</code> to the interface required by\r
+<code>std::set/std::multiset</code>, thereby providing set/multiset and vector\r
+functionality (random access) in one container.</p>\r
+\r
+<p>Tests show that <code>sorted_vector</code>'s element retrieval (find) speed outperforms\r
+that of <code>std::set/std::multiset</code> by a factor of 2 (on most machines). On the downward side is \r
+the poor performance of <code>sorted_vector</code>'s insert member function, because it\r
+inserts an element somewhere in the middle of the sorted vector in order\r
+to preserve the sort order. By using <code>sorted_vector</code>'s low level interface one can\r
+solve this performance bottleneck by inserting a bunch of objects using a series of \r
+<code>push_back</code>'s followed by a call to the member function <code>sort</code>, which restores the sort\r
+order. </p>\r
+\r
+<p><code>sorted_vector</code> should be preferred over <code>std::set/std::multiset</code> \r
+if many small elements\r
+must be stored. Most STL implementations use a variant of a balanced tree to \r
+implement set and multiset, which imposes a per element storage overhead of 3 pointers.\r
+The most important reason to use a <code>std::set/std::multiset</code> instead of \r
+<code>sorted_vector</code> is\r
+the need to keep iterators into a set/multiset while inserting more elements into\r
+the set. These iterators remain valid in the case of a set/multiset, but are invalidated\r
+in the case of a <code>sorted_vector</code> container. </p>\r
+\r
+<h2>Namespace</h2>\r
+<p><code>sorted_vector</code> resides in the namespace <code>codeproject</code>.</p>\r
+\r
+<h2>Basic Usage</h2>\r
+\r
+<p>The following small table shows corresponding declarations of <code>sorted_vector</code>'s \r
+and <code>set</code>'s/<code>multiset</code>'s.</p>\r
+\r
+<Table border=1>\r
+<TR>\r
+<TH>STL concept</TH>\r
+<TH>std library</TH>\r
+<TH>sorted_vector</TH>\r
+</TR>\r
+<TR>\r
+<TD VAlign=top>set</TD>\r
+<TD VAlign=top><code>set<Key,Pred></code></TD>\r
+<TD VAlign=top><code>sorted_vector<Key,<span class='cpp-keyword'>true</span>,Pred></code></TD>\r
+</TR>\r
+<TD VAlign=top>multiset</TD>\r
+<TD VAlign=top><code>mutliset<Key,Pred></code></TD>\r
+<TD VAlign=top><code>sorted_vector<Key,Pred></code></TD>\r
+</Table>\r
+\r
+<p>(<code>sorted_vector<Key,Pred,<span class='cpp-keyword'>true</span>></code> means <code>sorted_vector<Key,Pred,bNoDuplicates=<span class='cpp-keyword'>true</span>></code>)</p>\r
+\r
+<P>The various set/multiset <code>insert</code> and <code>erase</code> member functions as well as the\r
+set/multiset functions <code>count, lower_bound,upper_bound, equal_range</code> are part of \r
+<code>sorted_vector</code>'s interface and behave the same as there set/multiset counterparts.\r
+The following code snippet shows the use of a <code>sorted_vector</code> to hold the\r
+set intersection of the content of two <code>std::vector</code>'s.</p>\r
+\r
+<pre><span class="code-preprocessor">#pragma</span> warning(disable:<span class="code-digit">4786</span>)\r
+#include <span class="code-string">"</span><span class="code-string">sorted_vector.h"</span>\r
+size_t <span class="code-comment">//</span><span class="code-comment">build intersection using set interface of sorted_vector\r
+</span>BuildIntersection( <span class="code-keyword">const</span> std::vector<<span class="code-keyword">int</span>>& v0,<span class="code-keyword">const</span> std::vector<<span class="code-keyword">int</span>>& v1,\r
+ codeproject::sorted_vector<<span class="code-keyword">int</span>,<span class="code-keyword">true</span>>& svecIntersection)\r
+{ \r
+ codeproject::sorted_vector<<span class="code-keyword">int</span>,<span class="code-keyword">true</span>> svec(v0.begin(),v0.end());\r
+ <span class="code-keyword">for</span>(<span class="code-keyword">int</span> i=0;i<v1.size();i++){\r
+ <span class="code-keyword">if</span>( svec.find(v1[i])!=svec.end() ){\r
+ svecIntersection.insert(v1[i]);\r
+ }\r
+ }\r
+ <span class="code-keyword">return</span> svecIntersection.size();\r
+}\r
+</pre>\r
+\r
+<p>The code example shows the use of the member functions <code>find</code> and <code>insert</code>. \r
+If you replace <code>codeproject::sorted_vector<<span class='cpp-keyword'>int</span>,<span class='cpp-keyword'>true</span>></code> by <code>std::set<<span class='cpp-keyword'>int</span>></code> you get exactly\r
+the same result. This piece of code can be optimized for speed by replacing the insert calls in the loop \r
+by calls to <code>push_back</code> of the base container (a vector) followed by a call \r
+to the member function <code>sort</code> at the end of the loop.</p>\r
+\r
+<pre><span class="code-preprocessor">#pragma</span> warning(disable:<span class="code-digit">4786</span>)\r
+<span class="code-preprocessor">#include</span><span class="code-preprocessor"> <span class="code-string">"</span><span class="code-string">sorted_vector.h"</span>\r
+</span><span class="code-sdkkeyword">size_t</span> <span class="code-comment">//</span><span class="code-comment">same as previous example, optimized insertions \r
+</span>BuildIntersection1( <span class="code-keyword">const</span> std::vector<<span class="code-keyword">int</span>>& v0,<span class="code-keyword">const</span> std::vector<<span class="code-keyword">int</span>>& v1,\r
+ codeproject::sorted_vector<<span class="code-keyword">int</span>,<span class="code-keyword">true</span>>& svecIntersection)\r
+{ \r
+ codeproject::sorted_vector<<span class="code-keyword">int</span>,<span class="code-keyword">true</span>> svec(v0.begin(),v0.end());\r
+ codeproject::sorted_vector<<span class="code-keyword">int</span>,<span class="code-keyword">true</span>>::Cont& vInterSect \r
+ = svecIntersection.get_container();\r
+ <span class="code-keyword">for</span>(<span class="code-keyword">int</span> i=0;i<v1.size();i++){\r
+ <span class="code-keyword">if</span>( svec.find(v1[i])!=svec.end() ){\r
+ vInterSect.push_back(v1[i]);\r
+ }\r
+ }\r
+ svecIntersection.sort();\r
+ <span class="code-keyword">return</span> svecIntersection.size();\r
+}\r
+</pre>\r
+\r
+<h2>Interface of sorted_vector </h2>\r
+<Table border=1>\r
+<TR>\r
+<TH>\r
+Member\r
+</TH>\r
+<TH>\r
+Coming from\r
+</TH>\r
+<TH>\r
+Description\r
+</TH>\r
+</TR>\r
+<TR>\r
+<TD VAlign=top><code>Cont</code></TD>\r
+<TD VAlign=top>sorted_vector</TD>\r
+<TD VAlign=top>container type, the type of the container used to store the controlled sequence.</TD>\r
+</TR>\r
+<TR>\r
+<TD VAlign=top><code>value_type</code></TD>\r
+<TD VAlign=top>vector</TD>\r
+<TD VAlign=top>The type of object, T, stored in the set.</TD>\r
+</TR>\r
+<TR>\r
+<TD VAlign=top><code>key_type</code></TD>\r
+<TD VAlign=top>set/multiset</TD>\r
+<TD VAlign=top>The key type associated with value_type.</TD>\r
+</TR>\r
+<TR>\r
+<TD VAlign=top><code>key_compare</code></TD>\r
+<TD VAlign=top>set/multiset</TD>\r
+<TD VAlign=top>Function object that compares two keys for ordering.</TD>\r
+</TR>\r
+<TR>\r
+<TD VAlign=top><code>value_compare</code></TD>\r
+<TD VAlign=top>set/multiset</TD>\r
+<TD VAlign=top>Function object that compares two values for ordering.</TD>\r
+</TR>\r
+<TR>\r
+<TD VAlign=top><code>pointer</code></TD>\r
+<TD VAlign=top>vector</TD>\r
+<TD VAlign=top>Pointer to T.</TD>\r
+</TR>\r
+<TR>\r
+<TD VAlign=top><code>reference</code></TD>\r
+<TD VAlign=top>vector</TD>\r
+<TD VAlign=top>Reference to T</TD>\r
+</TR>\r
+<TR>\r
+<TD VAlign=top><code>const_reference</code></TD>\r
+<TD VAlign=top>vector</TD>\r
+<TD VAlign=top>Const reference to T</TD>\r
+</TR>\r
+<TR>\r
+<TD VAlign=top><code>size_type</code></TD>\r
+<TD VAlign=top>vector</TD>\r
+<TD VAlign=top>An unsigned integral type.</TD>\r
+</TR>\r
+<TR>\r
+<TD VAlign=top><code>difference_type</code></TD>\r
+<TD VAlign=top>vector</TD>\r
+<TD VAlign=top>A signed integral type.</TD>\r
+</TR>\r
+<TR>\r
+<TD VAlign=top><code>iterator</code></TD>\r
+<TD VAlign=top>vector</TD>\r
+<TD VAlign=top>Random access iterator used to iterate through a vector.</TD>\r
+</TR>\r
+<TR>\r
+<TD VAlign=top><code>const_iterator</code></TD>\r
+<TD VAlign=top>vector</TD>\r
+<TD VAlign=top>Random access const iterator used to iterate through a vector</TD>\r
+</TR>\r
+<TR>\r
+<TD VAlign=top><code>reverse_iterator</code></TD>\r
+<TD VAlign=top>vector</TD>\r
+<TD VAlign=top>Random access iterator used to iterate backwards through a vector.\r
+</TD>\r
+</TR>\r
+<TR>\r
+<TD VAlign=top><code>const_reverse_iterator</code></TD>\r
+<TD VAlign=top>vector</TD>\r
+<TD VAlign=top>Random access const iterator used to iterate backwards through a vector.</TD>\r
+</TR>\r
+<TR>\r
+<TD VAlign=top><code>iterator begin() <span class='cpp-keyword'>const</span></code></TD>\r
+<TD VAlign=top>vector</A></TD>\r
+<TD VAlign=top>Returns an iterator pointing to the beginning of the sorted_vector.</TD>\r
+</TR>\r
+<TR>\r
+<TD VAlign=top><code>iterator end() <span class='cpp-keyword'>const</span></code></TD>\r
+<TD VAlign=top>vector</TD>\r
+<TD VAlign=top>Returns an iterator pointing to the end of the sorted_vector.</TD>\r
+</TR>\r
+<TR>\r
+<TD VAlign=top><code>reverse_iterator rbegin() <span class='cpp-keyword'>const</span></code></TD>\r
+<TD VAlign=top>vector</TD>\r
+<TD VAlign=top>Returns a reverse_iterator pointing to the beginning of the reversed sorted_vector</TD>\r
+</TR>\r
+<TR>\r
+<TD VAlign=top><code>reverse_iterator rend() <span class='cpp-keyword'>const</span></code></TD>\r
+<TD VAlign=top>vector</A></TD>\r
+<TD VAlign=top>Returns a reverse_iterator pointing to the end of the reversed sorted_vector.</TD>\r
+</TR>\r
+<TR>\r
+<TD VAlign=top><code>size_type size() <span class='cpp-keyword'>const</span></code></TD>\r
+<TD VAlign=top>vector</TD>\r
+<TD VAlign=top>Returns the size of the sorted_vector.</TD>\r
+</TR>\r
+<TR>\r
+<TD VAlign=top><code>size_type max_size() <span class='cpp-keyword'>const</span></code></TD>\r
+<TD VAlign=top>vector</A></TD>\r
+<TD VAlign=top>Returns the largest possible size of the sorted_vector.</TD>\r
+</TR>\r
+<TR>\r
+<TD VAlign=top><code><span class='cpp-keyword'>bool</span> empty() <span class='cpp-keyword'>const</span></code></TD>\r
+<TD VAlign=top>vector</TD>\r
+<TD VAlign=top>true if the sorted_vec's size is 0.</TD>\r
+</TR>\r
+<TR>\r
+<TD VAlign=top><code>key_compare key_comp() <span class='cpp-keyword'>const</span></code></TD>\r
+<TD VAlign=top>set/multiset</A></TD>\r
+<TD VAlign=top>Returns the key_compare object used by the sorted_vector.</TD>\r
+</TR>\r
+<TR>\r
+<TD VAlign=top><code>value_compare value_comp() <span class='cpp-keyword'>const</span></code></TD>\r
+<TD VAlign=top>set/multiset</TD>\r
+<TD VAlign=top>Returns the value_compare object used by the sorted_vector.</TD>\r
+</TR>\r
+<TR>\r
+<TD VAlign=top><code>sorted_vector()</code></TD>\r
+<TD VAlign=top>set/multiset</TD>\r
+<TD VAlign=top>Creates an empty sorted_vector.</TD>\r
+</TR>\r
+<TR>\r
+<TD VAlign=top><code>sorted_vector(<span class='cpp-keyword'>const</span> key_compare& comp)</code></TD>\r
+<TD VAlign=top>set/multiset</TD>\r
+<TD VAlign=top>Creates an empty sorted_vector, using comp as the key_compare object.</TD>\r
+</TR>\r
+<TR>\r
+<TD VAlign=top><B>VC++7.0:<BR> </B><pre><span class="code-keyword">template</span> <<span class="code-keyword">class</span> InputIterator>\r
+sorted_vector(InputIterator f,\r
+ InputIterator l)</pre>\r
+ <BR><B>VC++6.0:<BR> </B><code>sorted_vector(const_iterator f, const_iterator l)</code> \r
+</TD>\r
+<TD VAlign=top>set/multiset</TD>\r
+<TD VAlign=top>Creates a sorted_vector with a copy of a range.</TD>\r
+</TR>\r
+<TR>\r
+<TD VAlign=top><B>VC++7.0:<BR> </B><pre><span class="code-keyword">template</span> <<span class="code-keyword">class</span> InputIterator>\r
+sorted_vector(InputIterator f,\r
+InputIterator l,<span class="code-keyword">const</span> key_compare& comp)</pre>\r
+ <BR><B>VC++6.0:<BR> </B><code>sorted_vector(const_iterator f, const_iterator l,<span class='cpp-keyword'>const</span> key_compare& comp)</code> \r
+</TD>\r
+<TD VAlign=top>set/multiset</TD>\r
+<TD VAlign=top>Creates a sorted_vector with a copy of a range, using comp as the key_compare object.</TD>\r
+</TR>\r
+<TR>\r
+<TD VAlign=top><code>sorted_vector(<span class='cpp-keyword'>const</span> sorted_vector&)</code></TD>\r
+<TD VAlign=top>set/multiset</TD>\r
+<TD VAlign=top>The copy constructor.</TD>\r
+</TR>\r
+<TR>\r
+<TD VAlign=top><code>sorted_vector& <span class='cpp-keyword'>operator</span>=(<span class='cpp-keyword'>const</span> sorted_vector&)</code></TD>\r
+<TD VAlign=top>set/multiset</TD>\r
+<TD VAlign=top>The assignment operator (assigns other sorted_vector )</TD>\r
+</TR>\r
+<TR>\r
+<TD VAlign=top><code>sorted_vector& <span class='cpp-keyword'>operator</span>=(<span class='cpp-keyword'>const</span> Cont&)</code></TD>\r
+<TD VAlign=top>sorted_vector</TD>\r
+<TD VAlign=top>The assignment operator (assigns other vector<T> )</TD>\r
+</TR>\r
+<TR>\r
+<TD VAlign=top><code><span class='cpp-keyword'>void</span> swap(sorted_vector&)</code></TD>\r
+<TD VAlign=top>set/multiset</TD>\r
+<TD VAlign=top>Swaps the contents of two sorted_vector's</TD>\r
+</TR>\r
+<TR>\r
+<TD VAlign=top><code>pair<iterator, <span class='cpp-keyword'>bool</span>>insert(<span class='cpp-keyword'>const</span> value_type& x)</code></TD>\r
+<TD VAlign=top>set/multiset</TD>\r
+<TD VAlign=top>Inserts x into the sorted_vector.</TD>\r
+</TR>\r
+<TR>\r
+<TD VAlign=top><code>iterator insert(iterator pos, <span class='cpp-keyword'>const</span> value_type& x)</code></TD>\r
+<TD VAlign=top>set/multiset</TD>\r
+<TD VAlign=top>Inserts x into the sorted_vector, using pos as a hint to where it will be\r
+ inserted.\r
+</TD>\r
+</TR>\r
+<TR>\r
+<TD VAlign=top><B>VC++7.0:<BR> </B><pre><span class="code-keyword">template</span> <<span class="code-keyword">class</span> InputIterator>\r
+<span class="code-keyword">void</span> insert(InputIterator f, InputIterator l)</pre>\r
+ <BR><B>VC++6.0:<BR> </B><code><span class='cpp-keyword'>void</span> insert(const_iterator first f, const_iterator l)</code>\r
+</TD>\r
+<TD VAlign=top>set/multiset</TD>\r
+<TD VAlign=top>Inserts a range into the sorted_vector.</TD>\r
+</TR>\r
+<TR>\r
+<TD VAlign=top><code><span class='cpp-keyword'>void</span> erase(iterator pos)</code></TD>\r
+<TD VAlign=top>vector</TD>\r
+<TD VAlign=top>Erases the element pointed to by pos.</TD>\r
+</TR>\r
+<TR>\r
+<TD VAlign=top><code>size_type erase(<span class='cpp-keyword'>const</span> key_type& k)</code></TD>\r
+<TD VAlign=top>set/multiset</A></TD>\r
+<TD VAlign=top>Erases the element whose key is k.</TD>\r
+</TR>\r
+<TR>\r
+<TD VAlign=top><code><span class='cpp-keyword'>void</span> erase(iterator first, iterator last)</code></TD>\r
+<TD VAlign=top>vector</A></TD>\r
+<TD VAlign=top>Erases all elements in a range.</TD>\r
+</TR>\r
+<TR>\r
+<TD VAlign=top><code><span class='cpp-keyword'>void</span> clear()</code></TD>\r
+<TD VAlign=top>vector</A></TD>\r
+<TD VAlign=top>Erases all of the elements.</TD>\r
+</TR>\r
+<TR>\r
+<TD VAlign=top><pre>iterator\r
+ find(<span class="code-keyword">const</span> key_type& k) <span class="code-keyword">const</span></pre></TD>\r
+<TD VAlign=top>set/multiset</TD>\r
+<TD VAlign=top>Finds an element whose key is k.</TD>\r
+</TR>\r
+<TR>\r
+<TD VAlign=top><pre>size_type\r
+ count(<span class="code-keyword">const</span> key_type& k) <span class="code-keyword">const</span></pre></TD>\r
+<TD VAlign=top>set/multiset</A></TD>\r
+<TD VAlign=top>Counts the number of elements whose key is k.</TD>\r
+</TR>\r
+<TR>\r
+<TD VAlign=top><pre>iterator\r
+ lower_bound(<span class="code-keyword">const</span> key_type& k) <span class="code-keyword">const</span></pre></TD>\r
+<TD VAlign=top>set/multiset</TD>\r
+<TD VAlign=top>Finds the first element whose key is not less than k.</TD>\r
+</TR>\r
+<TR>\r
+<TD VAlign=top><pre>iterator\r
+ upper_bound(<span class="code-keyword">const</span> key_type& k) <span class="code-keyword">const</span></pre></TD>\r
+<TD VAlign=top>set/multiset</TD>\r
+<TD VAlign=top>Finds the first element whose key is greater than k.</TD>\r
+</TR>\r
+<TR>\r
+<TD VAlign=top><pre>pair<iterator, iterator>\r
+equal_range(<span class="code-keyword">const</span> key_type& k) <span class="code-keyword">const</span></pre></TD>\r
+<TD VAlign=top>set/multiset</TD>\r
+<TD VAlign=top>Finds a range containing all elements whose key is k.</TD>\r
+</TR>\r
+<TR>\r
+<TD VAlign=top><code><span class='cpp-keyword'>bool</span> <span class='cpp-keyword'>operator</span>==(<span class='cpp-keyword'>const</span> sorted_vector&,<span class='cpp-keyword'>const</span> sorted_vector&)</code></TD>\r
+<TD VAlign=top>vector</TD>\r
+<TD VAlign=top>Tests two sorted_vector for equality. This is a global function, not a member function.\r
+There is also an operator !=</TD>\r
+</TR>\r
+<TR>\r
+<TD VAlign=top><code><span class='cpp-keyword'>bool</span> <span class='cpp-keyword'>operator</span><(<span class='cpp-keyword'>const</span> sorted_vector&, <span class='cpp-keyword'>const</span> sorted_vector&)</code></TD>\r
+<TD VAlign=top>vector</TD>\r
+<TD VAlign=top>Lexicographical comparison. This is a global function, not a member function.\r
+ There are also operators <= >= and ></TD>\r
+</TR>\r
+<TR>\r
+<TD VAlign=top><code>Cont& get_container()</code></TD>\r
+<TD VAlign=top>sorted_vector</TD>\r
+<TD VAlign=top>Returns a reference to the internal vector used to store the controlled sequence</TD>\r
+</TR>\r
+<TR>\r
+<TD VAlign=top><code><span class='cpp-keyword'>void</span> sort()</code></TD>\r
+<TD VAlign=top>sorted_vector</TD>\r
+<TD VAlign=top>Restores the sort order using key_compare </TD>\r
+</TR>\r
+<TR>\r
+<TD VAlign=top><code>reference at(size_type i)</code></TD>\r
+<TD VAlign=top>sorted_vector</TD>\r
+<TD VAlign=top>Returns a reference to the element at *(begin()+i) with range check</TD>\r
+</TR>\r
+<TR>\r
+<TD VAlign=top><code>const_reference at(size_type i) <span class='cpp-keyword'>const</span></code></TD>\r
+<TD VAlign=top>sorted_vector</TD>\r
+<TD VAlign=top>Returns a reference to the element at *(begin()+i) with range check</TD>\r
+</TR>\r
+<TR>\r
+<TD VAlign=top><code>const_reference <span class='cpp-keyword'>operator</span>[](size_type i) <span class='cpp-keyword'>const</span></code></TD>\r
+<TD VAlign=top>sorted_vector</TD>\r
+<TD VAlign=top>Returns a reference to the element at *(begin()+i)</TD>\r
+</TR>\r
+<TR>\r
+<TD VAlign=top><code>reference <span class='cpp-keyword'>operator</span>[](size_type i)</code></TD>\r
+<TD VAlign=top>sorted_vector</TD>\r
+<TD VAlign=top>Returns a reference to the element at *(begin()+i)</TD>\r
+</TR>\r
+<TR>\r
+<TD VAlign=top><code>const_reference front() <span class='cpp-keyword'>const</span></code></TD>\r
+<TD VAlign=top>sorted_vector</TD>\r
+<TD VAlign=top>Returns a reference to the first element</TD>\r
+</TR>\r
+<TR>\r
+<TD VAlign=top><code>reference front()</code></TD>\r
+<TD VAlign=top>sorted_vector</TD>\r
+<TD VAlign=top>Returns a reference to the first element</TD>\r
+</TR>\r
+<TR>\r
+<TD VAlign=top><code>reference back()</code></TD>\r
+<TD VAlign=top>sorted_vector</TD>\r
+<TD VAlign=top>Returns a reference to the last element</TD>\r
+</TR>\r
+<TR>\r
+<TD VAlign=top><code>const_reference back() <span class='cpp-keyword'>const</span></code></TD>\r
+<TD VAlign=top>sorted_vector</TD>\r
+<TD VAlign=top>Returns a reference to the last element</TD>\r
+</TR>\r
+<TR>\r
+<TD VAlign=top><code><span class='cpp-keyword'>void</span> pop_back() </code> </TD>\r
+<TD VAlign=top>sorted_vector</TD>\r
+<TD VAlign=top>Removes the last element from the sorted_vector</TD>\r
+</TR>\r
+</table>\r
+\r
+\r
+\r
+<h2>Points of Interest</h2>\r
+\r
+<p>An interview with Alexander Stepanov (inventor of the STL) at\r
+<A href="http://www.stlport.org/resources/StepanovUSA.html">http://www.stlport.org/resources/StepanovUSA.html</A>\r
+, in which he proposed to implement\r
+a sorted container as an adapter of a <code>std::container</code> gave me the idea for this work.\r
+The real surprise to me was the unexpected good performance of <code>sorted_vector</code> compared\r
+to set/multiset. The outcome of my tests indicate, that the <code>std::set/std::multiset</code>\r
+has only one (important) advantage over a sorted vector, namely that iterators remain\r
+valid in a set/multiset, even when more elements are added.\r
+</p>\r
+\r
+<p>The implementation work itself was easy and did not require any advanced C++/STL feature.\r
+It can be summarized as follows:\r
+Most of the member functions of <code>sorted_vector</code> forward the call to the <code>vec_</code> data member,\r
+which is a <code>std::vector</code>. The set/multiset specific functions for inserting/erasing and\r
+locating elements mostly use STL algorithms to deal with the sorted sequence present\r
+in the <code>vec_</code> data member. The low level interface consisting of the member functions\r
+ <code>get_container()</code> (which returns a reference to the <code>vec_</code> data member) \r
+and <code>sort</code> and <code>stable_sort</code> \r
+ (which restore the sort order) are necessary to improve insertion performance (by allowing\r
+ a temporary violation of the sorting order).\r
+Only one function was unexpectedly difficult to implement: The function <code>unique</code>, which\r
+must be called after <code>sort</code> and <code>stable_sort</code> in the case of a set. \r
+This function is part of the STL and requires a predicate as third argument. This predicate must return true,\r
+if the passed elements are equal. But the class <code>sorted_vector</code> only has access to a predicate\r
+which evaluates the < relation. In theory, it should be possible, to transform a predicate\r
+evaluating the < relation into another predicate evaluating ==, but in practice this is only\r
+possible, when the < predicate is implemented as object derived from <code>std::binary_function</code>.\r
+Ultimately, I had to implement <code>unique</code> myself because of that. </p>\r
+\r
+<h2>History</h2>\r
+<ul><li>1.0: November 19th, 2002; Initial release. </li>\r
+<li>1.1: November 28th, 2002; Documentation and code Update\r
+ <ul><li>changed namespace from <code>std</code> to <code>codeproject</code></li>\r
+ <li>supports member templates for constructing/inserting from iterator range in case of VC++7.0</li>\r
+ </ul>\r
+</li>\r
+</ul>\r
+\r
+\r
+ </div>\r
+ \r
+\r
+ <div class="float-right" style="margin:20px 0 0 0;border:1px solid #ccc">\r
+ \r
+ </div>\r
+ \r
+ \r
+ \r
+ <h2>License</h2>\r
+ <div id="LicenseTerms"><p>This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.</p><p>A list of licenses authors might use can be found <a href="/info/Licenses.aspx">here</a></p></div>\r
+ \r
+\r
+ \r
+ <h2>Share</h2>\r
+ <div style="margin-bottom:40px;width:385px">\r
+ \r
+ </div> \r
+ \r
+\r
+\r
+ \r
+ <h2 id="ctl00_AboutHeading">About the Author</h2>\r
+ \r
+\r
+<div class="container">\r
+<div style="width:210px;overflow:hidden;float:left;text-align:center">\r
+ <img id="ctl00_AboutAuthorRptr_ctl00_AboutAuthor_memberPhoto" class="profile-pic" src="//dj9okeyxktdvd.cloudfront.net/script/Membership/Images/member_unknown.gif" border="0" style="transform:rotate(-3deg);" />\r
+</div>\r
+<div class="container-member float-left" style="margin-top:35px;">\r
+ <b><a id="ctl00_AboutAuthorRptr_ctl00_AboutAuthor_memberProfileLink" class="author" href="/Members/Martin-Holzherr">Martin Holzherr</a></b>\r
+ <div class="company">\r
+ <span id="ctl00_AboutAuthorRptr_ctl00_AboutAuthor_memberJobTitle"></span>\r
+ <span id="ctl00_AboutAuthorRptr_ctl00_AboutAuthor_memberCompany"></span> \r
+ <br /><span id="ctl00_AboutAuthorRptr_ctl00_AboutAuthor_memberLocation">Switzerland <img src="/script/Geo/Images/CH.gif" alt="Switzerland" width="16px" height="11px" /></span>\r
+ </div>\r
+</div>\r
+ \r
+<div class="padded-top float-left clearfix">\r
+ No Biography provided\r
+\r
+ \r
+\r
+ \r
+</div>\r
+</div><br />\r
+ \r
+ \r
+\r
+ <div class="clearfix"></div>\r
+\r
+ <div style="padding-top:8px">\r
+ \r
+ </div>\r
+\r
+ \r
+ <div style="margin:auto;height:90px;margin-top:10px;Widt:730px"> \r
+ \r
+ </div>\r
+ \r
+ \r
+\r
+ \r
+ </form>\r
+\r
+ </div>\r
+\r
+ \r
+ \r
+\r
+ <h2>Comments and Discussions</h2>\r
+ \r
+ <p><img alt="Comment" src="/script/forums/images/NewComment.gif" width="12px" height="16px" />\r
+ <b>20 messages</b> have been posted for this article \r
+ Visit <b><a id="ctl00_ArticleLink" href="/Articles/3217/An-STL-compliant-sorted-vector">http://www.codeproject.com/Articles/3217/An-STL-compliant-sorted-vector</a></b> to post and view comments on \r
+ this article, or click <b><a id="ctl00_PrintWithMessage" href="/Articles/3217/An-STL-compliant-sorted-vector?display=PrintAll">here</a></b> \r
+ to get a print view with messages.</p>\r
+ \r
+ \r
+\r
+ </div>\r
+ \r
+ </td>\r
+ <td width="170px">\r
+ \r
+ </td>\r
+ </tr></table>\r
+\r
+ \r
+ <div class="theme1-background" style="height:2px" id="stickyStop"></div>\r
+\r
+ <div class="extended tiny-text">\r
+ <div class="row">\r
+ <div class="float-left">\r
+ <a id="ctl00_PermaLink" itemprop="url" href="/Articles/3217/An-STL-compliant-sorted-vector">Permalink</a> | \r
+ <a id="ctl00_AdvertiseLink" href="http://developermedia.com/">Advertise </a> |\r
+ <a id="ctl00_PrivacyLink" href="/info/privacy.aspx">Privacy</a> |\r
+ <a id="ctl00_Mobile" rel="nofollow" href="/Articles/3217/An-STL-compliant-sorted-vector?display=Mobile">Mobile</a>\r
+ <br />\r
+ \r
+ \r
+ Web02 |\r
+ 2.8.140814.1 |\r
+ Last Updated 29 Nov 2002 \r
+ </div>\r
+ <div class="float-right align-right">\r
+ Article Copyright 2002 by Martin Holzherr<br />Everything else\r
+ Copyright © <a href="mailto:webmaster@codeproject.com">CodeProject</a>, 1999-2014 <br />\r
+ <a id="ctl00_TermsOfUseLink" href="/info/TermsOfUse.aspx">Terms of Service</a>\r
+ </div>\r
+\r
+ \r
+\r
+ </div>\r
+ </div>\r
+ \r
+\r
+ <br clear="all" />\r
+ \r
+ \r
+\r
+ </div> \r
+ </div>\r
+</div>\r
+\r
+\r
+<div style="display:none;" id="dm_AdTable">\r
+ \r
+</div>\r
+\r
+\r
+\r
+\r
+\r
+\r
+<script type="text/javascript" language="Javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script><script type='text/javascript'>//<![CDATA[
+if (typeof jQuery == 'undefined') {
+ document.write(unescape("%3Cscript src='/script/JS/jquery-1.6.2.min.js' type='text/javascript' %3E%3C/script%3E"));
+}//]]></script>\r
+<script type="text/javascript" language="Javascript">//<![CDATA[\r
+$(document).ready(function() { anchorAnimate();
+$('#ctl00_RightSideBar').sticky($('#stickyStop'));
+$('#ctl00_Nav').sticky($('#stickyStop'));
+});\r
+\r
+//]]>\r
+</script>\r
+\r
+\r
+</body>\r
+</html>
\ No newline at end of file