Permalink
Switch branches/tags
Nothing to show
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
351 lines (258 sloc) 37.9 KB

 

 

 

 

 

(C++) Container

 

A container is a class type for containing zero, one or multiple instances of one or more data types.

 

Every container has its own advantages and disadvantages. For example a std::vector has random-access reading/writing, but new elements can only be added at the begin and end of the container. For a std::list, this is the other way around.

 

 

 

 

 

 

STL containers (incomplete list)

 

 

 

 

 

 

SGI extension containers (incomplete list)

 

  • bit_vector
  • hash_set
  • hash_map
  • hash_multiset
  • hash_multimap
  • hash
  • rope

 

 

 

 

 

Boost containers (incomplete list)

 

 

 

 

 

 

Container code snippets

 

 

 

 

 

 

Advice

 

 

 

 

 

 

References

 

  1. Bjarne Stroustrup. The C++ Programming Language (4th edition). 2013. ISBN: 978-0-321-56384-2. Chapter 17.7. Advice. page 525: '[8] If a class is a container, give it an initializer-list constructor'
  2. Bjarne Stroustrup. The C++ Programming Language (4th edition). 2013. ISBN: 978-0-321-56384-2. Chapter 23.8, page 698: '[2] Use templates to express containers'
  3. Bjarne Stroustrup. The C++ Programming Language (4th edition). 2013. ISBN: 978-0-321-56384-2. Chapter 31.6. Advice. page 924: '[1] An STL container defines a sequence'
  4. Bjarne Stroustrup. The C++ Programming Language (4th edition). 2013. ISBN: 978-0-321-56384-2. Chapter 31.6. Advice. page 924: '[2] Use vector as your default container'
  5. Bjarne Stroustrup. The C++ Programming Language (4th edition). 2013. ISBN: 978-0-321-56384-2. Chapter 31.6. Advice. page 924: '[3] Insertion operators, such as insert() and push_back() are often more efficient on a vector than on a list'
  6. Bjarne Stroustrup. The C++ Programming Language (4th edition). 2013. ISBN: 978-0-321-56384-2. Chapter 31.6. Advice. page 924: '[7] STL containers are resource handles'
  7. Bjarne Stroustrup. The C++ Programming Language (4th edition). 2013. ISBN: 978-0-321-56384-2. Chapter 31.6. Advice. page 924: '[13] Pass a container by reference and return a container by value'
  8. Bjarne Stroustrup. The C++ Programming Language (4th edition). 2013. ISBN: 978-0-321-56384-2. Chapter 31.6. Advice. page 924: '[14] For a container, use the ()-syntax for sizes and the {}-initializer syntax for lists of elements'
  9. Bjarne Stroustrup. The C++ Programming Language (4th edition). 2013. ISBN: 978-0-321-56384-2. Chapter 31.6. Advice. page 924: '[15] For simple traversal of a container, use a range-for-loop or a begin/end pair of iterators'
  10. Bjarne Stroustrup. The C++ Programming Language (4th edition). 2013. ISBN: 978-0-321-56384-2. Chapter 31.6. Advice. page 924: '[20] Use push_back() or resize() on a container, rather than realloc() on an array'
  11. Bjarne Stroustrup. The C++ Programming Language (4th edition). 2013. ISBN: 978-0-321-56384-2. Chapter 31.6. Advice. page 924: '[23] Do not assume that [] range checks'

Technical facts

 

 

 

 

 

 

./CppContainer/CppContainer.pri

 


INCLUDEPATH += \     ../../Classes/CppContainer SOURCES += \     ../../Classes/CppContainer/container.cpp HEADERS  += \     ../../Classes/CppContainer/container.h OTHER_FILES += \     ../../Classes/CppContainer/Licence.txt

 

 

 

 

 

./CppContainer/container.h

 


//--------------------------------------------------------------------------- /* Container, class with container class helper functions Copyright 2013-2015 Richel Bilderbeek This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ //--------------------------------------------------------------------------- //From http://www.richelbilderbeek.nl/CppContainer.htm //--------------------------------------------------------------------------- #ifndef RIBI_CONTAINER_H #define RIBI_CONTAINER_H #include <algorithm> #include <set> #include <string> #include <sstream> #include <vector> #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Weffc++" #pragma GCC diagnostic ignored "-Wunused-local-typedefs" #pragma GCC diagnostic pop namespace ribi { ///Class with container class helper functions struct Container {   Container();   bool AllAboutEqual(     const std::vector<double>& v,     const double tolerance   ) const noexcept;   ///Concatenate concatenates the strings, with a certain seperator   std::string Concatenate(const std::vector<std::string>& v, const std::string& seperator = "") const noexcept;   ///TODO: Merge with ToStr   std::string ContainerToStr(const std::vector<std::string>& s, const std::string& seperator = " ") const noexcept;   ///Shorthand for std::count(std::begin(t),std::end(t),u)   template <class T, class U>   static int Count(const T& t, const U& u) noexcept   {     return std::count(std::begin(t),std::end(t),u);   }   ///Obtain the version   std::string GetVersion() const noexcept;   ///Obtain the version history   std::vector<std::string> GetVersionHistory() const noexcept;   std::vector<std::string> SeperateString(     const std::string& input,     const char seperator) const noexcept;   template <class T>   static std::string ToStr(const std::set<T>& set) noexcept   {     std::stringstream s;     for (const auto& t: set) { s << t << ","; }     std::string str{s.str()};     if (!str.empty()) { str.pop_back(); }     str = "{" + str + "}";     return str;   }   template <class T>   static std::string ToStr(const std::vector<T>& v) noexcept   {     std::stringstream s;     for (const auto& t: v) { s << t << ","; }     std::string str{s.str()};     if (!str.empty()) { str.pop_back(); }     str = "{" + str + "}";     return str;   }   private:   #ifndef NDEBUG   static void Test() noexcept;   #endif }; } //~namespace ribi #endif // RIBI_CONTAINER_H

 

 

 

 

 

./CppContainer/container.cpp

 


//--------------------------------------------------------------------------- /* Container, class with container class helper functions Copyright 2013-2015 Richel Bilderbeek This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ //--------------------------------------------------------------------------- //From http://www.richelbilderbeek.nl/CppContainer.htm //--------------------------------------------------------------------------- #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Weffc++" #pragma GCC diagnostic ignored "-Wunused-local-typedefs" #pragma GCC diagnostic ignored "-Wunused-but-set-parameter" #include "container.h" #include <boost/algorithm/string/split.hpp> #include <boost/numeric/conversion/cast.hpp> #include "fuzzy_equal_to.h" #include "testtimer.h" #include "trace.h" #pragma GCC diagnostic pop template <class Container> std::string ContainerToStrImpl(const Container& c, const std::string& seperator) {   std::stringstream s;   std::copy(c.begin(),c.end(),     std::ostream_iterator<typename Container::value_type>(s,seperator.c_str()));   return s.str(); } ribi::Container::Container() {   #ifndef NDEBUG   Test();   #endif } bool ribi::Container::AllAboutEqual(   const std::vector<double>& v,   const double tolerance) const noexcept {   assert(!v.empty());   fuzzy_equal_to f(tolerance);   const double first_value{v[0]};   return std::count_if(     std::begin(v),     std::end(v),     [f,first_value](const double x) { return f(first_value,x); }   )     == boost::numeric_cast<int>(v.size())   ; } std::string ribi::Container::Concatenate(const std::vector<std::string>& v, const std::string& seperator) const noexcept {   std::stringstream s;   for (const auto& t: v) { s << t << seperator; }   std::string str = s.str();   //Remove seperator   if (!str.empty())   {     str.resize(str.size() - seperator.size());   }   return str; } std::string ribi::Container::ContainerToStr(   const std::vector<std::string>& s,   const std::string& seperator ) const noexcept {   return ContainerToStrImpl(s,seperator); } std::string ribi::Container::GetVersion() const noexcept {   return "1.2"; } std::vector<std::string> ribi::Container::GetVersionHistory() const noexcept {   return {     "2014-xx-xx: Version 1.0: initial version",     "2014-06-14: Version 1.1: added SeperateString"     "2014-07-30: Version 1.2: added Concatenate"   }; } std::vector<std::string> ribi::Container::SeperateString(   const std::string& input,   const char seperator) const noexcept {   std::vector<std::string> v;   boost::algorithm::split(v,input,     std::bind2nd(std::equal_to<char>(),seperator),     boost::algorithm::token_compress_on);   return v; } #ifndef NDEBUG void ribi::Container::Test() noexcept {   {     static bool is_tested{false};     if (is_tested) return;     is_tested = true;   }   const TestTimer test_timer(__func__,__FILE__,1.0);   const bool verbose{false};   const Container c;   if (verbose) { TRACE("Concatenate: empty vector with empty seperator must result in an empty string"); }   {     const std::vector<std::string> v{};     const std::string s{c.Concatenate(v,"")};     assert(s.empty());   }   if (verbose) { TRACE("Concatenate: empty vector with longer seperator must result in an empty string"); }   {     const std::vector<std::string> v{};     const std::string s{c.Concatenate(v,"[wont be used]")};     assert(s.empty());   }   if (verbose) { TRACE("Concatenate: vector with one string and empty seperator must result in that string"); }   {     const std::string s{"any string"};     const std::vector<std::string> v{s};     const std::string t{c.Concatenate(v,"")};     assert(s == t);   }   if (verbose) { TRACE("Concatenate: vector with one string and longer seperator must result in that string"); }   {     const std::string s{"any string again"};     const std::vector<std::string> v{s};     const std::string t{c.Concatenate(v,"[wont be used]")};     assert(s == t);   }   if (verbose) { TRACE("Concatenate: vector with two string and empty seperator must result in the summed string"); }   {     const std::string s{"any string"};     const std::string t{"goes on"};     const std::string expected{s+t};     const std::vector<std::string> v{s,t};     const std::string u{c.Concatenate(v,"")};     assert(u == expected);   }   if (verbose) { TRACE("Concatenate: vector with two string and longer seperator must result in the summed string"); }   {     const std::string s{"any string"};     const std::string t{"goes on"};     const std::string seperator{" "};     const std::string expected{s+seperator+t};     const std::vector<std::string> v{s,t};     const std::string u{c.Concatenate(v,seperator)};     assert(u == expected);   }   //SeperateString   {     { //Single input, seperator of type char       const auto v = c.SeperateString("a",',');       assert(v.size() == 1);       assert(v[0]=="a");     }     { //Two inputs, seperator of type char       const auto v = c.SeperateString("a,b",',');       assert(v.size() == 2);       assert(v[0]=="a");       assert(v[1]=="b");     }     {       //Five inputs, seperator of type char       const auto v = c.SeperateString("a,bb,ccc,dddd,eeeee",',');       assert(v.size() == 5);       assert(v[0]=="a");       assert(v[1]=="bb");       assert(v[2]=="ccc");       assert(v[3]=="dddd");       assert(v[4]=="eeeee");     }     { //Three inputs, of which one empty, seperator of type char       const auto v = c.SeperateString("a, ,ccc",',');       assert(v.size() == 3);       assert(v[0]=="a");       assert(v[1]==" ");       assert(v[2]=="ccc");     }   }   //AllAboutEqual   {     std::vector<double> v = { 0.9, 1.0, 1.1 };     assert(c.AllAboutEqual(v,1.0));     assert(!c.AllAboutEqual(v,0.01));   } } #endif