| 
				 | 
				
| Line 113: | 
Line 113: | 
 |      Now you should have build+run debug+release configurations, selectable in the weird project icon in bottom of left-side toolbar ("mode selector")  |  |      Now you should have build+run debug+release configurations, selectable in the weird project icon in bottom of left-side toolbar ("mode selector")  | 
 | |}  |  | |}  | 
 | {| class="mw-collapsible mw-collapsed wikitable"
  |  | 
 | ! boost release and debug build for linux
  |  | 
 | |-
  |  | 
 | |
  |  | 
 |     # download latest boost, eg: boost_1_59_0 
  |  | 
 |     m@wallee:~/development$ 7z x boost_1_59_0.7z
  |  | 
 |     cd boost_1_##_0
  |  | 
 |     build_boost_release_and_debug.sh
  |  | 
 |     # then patch .bashrc as instructed
  |  | 
 |     # eclipse and server/nix/bootstrap.sh are customized to match
  |  | 
 | To upgrade a project:
  |  | 
 |     cd nix
  |  | 
 |     make distclean  # removes nasty .deps folders that link to old boost if you let them
  |  | 
 |     make clean      # removes .o files etc
  |  | 
 |     cd ../build-Release && make distclean && make clean
  |  | 
 |     cd ../build-Debug && make distclean && make clean
  |  | 
 |     cd ..
  |  | 
 |     ./bootstrap force release
  |  | 
 |     ./bootstrap force debug
  |  | 
 | |}
  |  | 
 | {| class="mw-collapsible mw-collapsed wikitable"
  |  | 
 | ! boost release and debug build for Windows
  |  | 
 | |-
  |  | 
 | | Open a VS2015 x64 Native Tools Command Prompt.  
  |  | 
 | EITHER: for new installs, you have to run bootstrap.bat first, it will build b2; 
  |  | 
 | OR: for reruns, remove boost dirs: [bin.v2, stage].
  |  | 
 | Then build 64-bit:
  |  | 
 |  cd "....\boost_1_59_0"
  |  | 
 |  b2 toolset=msvc variant=release,debug link=static address-model=64
  |  | 
 |  rem trying to avoid excessive options, assuming I don't need these: threading=multi
  |  | 
 |  (old stuff)
  |  | 
 |        --toolset=msvc-14.0 address-model=64 --build-type=complete --stagedir=windows_lib\x64 stage
  |  | 
 |        Now open VS2013 x86 Native Tools Command Prompt and build 32-bit:
  |  | 
 |        cd "C:\Michael's Data\development\sixth_column\boost_1_55_0"
  |  | 
 |        bjam --toolset=msvc-12.0 address-model=32 --build-type=complete --stagedir=windows_lib\x86 stage
  |  | 
 | |}
  |  | 
 | {| class="mw-collapsible mw-collapsed wikitable"
  |  | 
 | ! c++11 include base constructor (etc) in derived class
  |  | 
 | |-
  |  | 
 | | The awesome C++11 way to steal the constructor from the base class, oh man I've been waiting for this one...
  |  | 
 |   class HttpsServer : public Server<HTTPS>
  |  | 
 |   {
  |  | 
 |     // DOES THIS FOR YOU!
  |  | 
 |     /*
  |  | 
 |     HttpsServer(unsigned short port, size_t num_threads, const std::string& cert_file, const std::string& private_key_file)
  |  | 
 |     :
  |  | 
 |         // Call base class
  |  | 
 |         Server<HTTPS>::Server(port, num_threads, cert_file, private_key_file)
  |  | 
 |     {}
  |  | 
 |     */
  |  | 
 |     using Server<HTTPS>::Server;
  |  | 
 |     ....
  |  | 
 | |}
  |  | 
 | {| class="mw-collapsible mw-collapsed wikitable"
  |  | 
 | ! c++11 containers
  |  | 
 | |-
  |  | 
 | | sorted_vector || use when doing lots of unsorted insertions and maintaining constant sort would be expensive; vector is good for a big pile of things that only occasionally needs a sorted lookup
  |  | 
 | |-
  |  | 
 | | map || sorted binary search tree; always sorted by key; you can walk through in sorted order (choose unordered if not needed!)
  |  | 
 | |-
  |  | 
 | | multimap || same as map but allows dupe keys (not as common)
  |  | 
 | |-
  |  | 
 | | unordered_map || hashmap; always sorted by key; additional bucket required for hash collisions; no defined order when walking through
  |  | 
 | |-
  |  | 
 | | unordered_multimap || same as map but allows dupe keys; dupes are obviously in the same bucket, and you can walk just the dupes if needed
  |  | 
 | |-
  |  | 
 | | set<br>multiset<br>unordered_set<br>unordered_multiset || sets are just like maps, except the key is embedded in the object, nice for encapsulation.<br />
  |  | 
 | Items must be const (!) since they are the key - sounds bad, but this is mitigated by the mutable keyword.<br />
  |  | 
 | You can use mutable on the variables that are not part of the key to remove the const.<br />
  |  | 
 | This changes the constness of the object from binary (completely const) to logical (constness is defined by the developer).<br />
  |  | 
 | So... set is a good way to achieve both encapsulation and logical const - make const work for you, not against!  :-)<br />
  |  | 
 | |-
  |  | 
 | | set (etc.) of pointers || sets of pointers are the pinnacle of object stores<br />
  |  | 
 | The entire object can be dereferenced and accessed then without const issues.<br />
  |  | 
 | A pointer functor can be provided that does a sort by dereferencing the pointer to the object.<br />
  |  | 
 | Two requirements: you must make sure yourself that you do not change the key values - you can mark them const, provided in constructor;<br />
  |  | 
 | you must create sort/equal/hash functors that dereference the pointers to use object contents<br />
  |  | 
 | (the default will be by pointer address).<br />
  |  | 
 | The arguably biggest advantage, as a result, is that you can create multiple sets<br />
  |  | 
 | to reference the same group of objects with different sort funtors to create multiple indices.<br />
  |  | 
 | You just have to manage the keys carefully, so that they don't change (which would invalidate the sorting).<br />
  |  | 
 | The primary container can manage object allocation; using a heap-based unique_ptr allocation<br />
  |  | 
 |     map vs key redux
  |  | 
 |                 
  |  | 
 |         use a key in the set, derive a class from it with the contents
  |  | 
 |             + small key
  |  | 
 |             + encapsulation
  |  | 
 |             - requires mutable to solve the const problem
  |  | 
 |         use a key in the set, key includes a mutable object
  |  | 
 |             + encapsulation
  |  | 
 |             - weird bc everything uses a const object but we have const functions like save() that change the mutable subobject
  |  | 
 |         use a map
  |  | 
 |             + small key
  |  | 
 |             - no encapsulation, have to deal with a pair instead of an object
  |  | 
 |                 can we just put a ref to key in the value?  sure why not - err, bc we don't have access to it
  |  | 
 |             + solves const problem bc value is totally mutable by design
  |  | 
 |             + we can have multiple keys - and the value can have multiple refs to them
  |  | 
 |             + simpler equal and hash functions
  |  | 
 |         map:
  |  | 
 |             create an object with internal key(s)
  |  | 
 |             create map index(es) with duplicate key values outside the object - dupe data is the downside
  |  | 
 |         use set(s) with one static key for find(): 
  |  | 
 |             create an object with internal key(s)
  |  | 
 |             create set index(es) with specific hash/equals functor(s)
  |  | 
 |             when finding, use one static key object (even across indexes!) so there isn't a big construction each time; just set the necessary key values
  |  | 
 |                 that proves difficult when dealing with member vars that are references
  |  | 
 |                 but to solve it, just set up a structure of dummy static key objects that use each other; then provide a function to setKey(Object& keyref) { keyref_ = keyref; }
  |  | 
 |                 nope, can't reassign refs
  |  | 
 |                 the solution: use pointers not references
  |  | 
 |                 yes that's right
  |  | 
 |                 just do it
  |  | 
 |                 apparently there was a reason i was anti-reference for all those years
  |  | 
 |                 two reasons to use pointers:
  |  | 
 |                     dynamically allocated
  |  | 
 |                     reassignment required
  |  | 
 |                 there ya go.  simple.  get it done. 
  |  | 
 |             when accessing find results from the set, use a const_cast on the object!
  |  | 
 |             WARNING: a separate base class with the key sounds good... but fails when you have more than one index on the object.  just use a static key object for them all!
  |  | 
 | 
  |  | 
 | |}
  |  | 
 | 
  |  | 
 | {| class="mw-collapsible mw-collapsed wikitable"
  |  | 
 | ! c++11 example for large groups of objects with frequent crud AND search
  |  | 
 | |-
  |  | 
 | | Best solution is an unordered set of pointers:
  |  | 
 |  typedef boost::unordered_set<MajorObject*> MajorObjects;
  |  | 
 | 
  |  | 
 | |}
  |  | 
 | 
  |  | 
 | {| class="mw-collapsible mw-collapsed wikitable"
  |  | 
 | ! c++11 example for large groups of objects with infrequent crud and frequent search
  |  | 
 | |-
  |  | 
 | | Best solution is a vector of pointers sorted on demand (sorted_vector):
  |  | 
 |  TODO
  |  | 
 | |}
  |  | 
 | 
  |  | 
 | {| class="mw-collapsible mw-collapsed wikitable"
  |  | 
 | ! c++11 example to associate two complex objects (one the map key, one the map value)
  |  | 
 | |-
  |  | 
 | | Use unordered_map with a custom object as key.  You must add hash and equals functions.  Boost makes it easy:
  |  | 
 |  static bool operator==(MyKeyObject const& m1, MyKeyObject const& m2)
  |  | 
 |  {
  |  | 
 |      return 
  |  | 
 |              m1.id_0 == m2.id_0
  |  | 
 |          &&  m1.id_1 == m2.id_1;
  |  | 
 |  }
  |  | 
 |  static std::size_t hash_value(MyKeyObject const& mko)
  |  | 
 |  {
  |  | 
 |      std::size_t seed = 0;
  |  | 
 |      boost::hash_combine(seed, mko.id_0);
  |  | 
 |      boost::hash_combine(seed, mko.id_1);
  |  | 
 |      return seed;
  |  | 
 |  }
  |  | 
 |  typedef boost::unordered_map<MyKeyObject, MyValueObject*> MyMap;
  |  | 
 | Note that you can extend this to use a pointer to a key object, whoop.
  |  | 
 | |}
  |  | 
 | 
  |  | 
 | {| class="mw-collapsible mw-collapsed wikitable"
  |  | 
 | ! c++11 example for multiple unordered_set indexes into one group of objects
  |  | 
 | |-
  |  | 
 | | Objects will be dynamically created.  One set should include them all and be responsible for memory allocation cleanup:
  |  | 
 |  TODO
  |  | 
 | |}
  |  | 
 | 
  |  | 
 | {| class="mw-collapsible mw-collapsed wikitable"
  |  | 
 | ! c++11 example for set with specific sorting
  |  | 
 | |-
  |  | 
 | | Use set with a specific sort functor.  You can create as many of these indexes as you want!
  |  | 
 |  struct customers_set_sort_functor
  |  | 
 |  {
  |  | 
 |      bool operator()(const MyObject* l, const MyObject* r) const
  |  | 
 |      {
  |  | 
 |          // the id is the key
  |  | 
 |          return l->id_ < r->id_;
  |  | 
 |      }
  |  | 
 |  };
  |  | 
 |  typedef set<MyObject*,myobject_sort_by_id_functor> MyObjectsById;
  |  | 
 | |}
  |  | 
 | 
  |  | 
 | {| class="mw-collapsible mw-collapsed wikitable"
  |  | 
 | ! c++11 loop through vector to erase some items
  |  | 
 | |-
  |  | 
 | | Note that other containers' iterators may not be invalidated so you can just erase() as needed...
  |  | 
 | For vectors, you have to play with iterators to get it right - watch for proper ++ pre/postfix!
  |  | 
 |  for (it = numbers.begin(); it != numbers.end(); )  // NOTE we increment below, only if we don't erase
  |  | 
 |  {
  |  | 
 |      if (*it.no_good()) 
  |  | 
 |      {
  |  | 
 |          numbers.erase(it++);  // NOTE that we ERASE THEN INCREMENT here.
  |  | 
 |      }
  |  | 
 |      else 
  |  | 
 |      {
  |  | 
 |          ++it;
  |  | 
 |      }
  |  | 
 |  }
  |  | 
 | I thought I had always looped backwards to do this, I *think* that's ok too, but I don't see it used in my code, I think I'll avoid.  :-)
  |  | 
 | |}
  |  | 
 | 
  |  | 
 | {| class="mw-collapsible mw-collapsed wikitable"
  |  | 
 | ! c++11 range based for loop, jacked with boost index if needed
  |  | 
 | |-
  |  | 
 | | No iterator usage at all.  Nice at times, not enough at others.  Make SURE to always use a reference or you will be working on a COPY.  Make it const if you aren't changing the object.
  |  | 
 |  for (auto& mc : my_container)
  |  | 
 |      mc.setString("default");
  |  | 
 |  for (const auto& cmc : my_container)
  |  | 
 |      cout << cmc.asString();
  |  | 
 | boost index can give you the index if you need it, sweet:
  |  | 
 |  #include <boost/range/adaptor/indexed.hpp>
  |  | 
 |  ...
  |  | 
 |  for (const auto &element: boost::adaptors::index(mah_container))
  |  | 
 |      cout << element.value() << element.index();
  |  | 
 | |}
  |  | 
 | 
  |  | 
 | {| class="mw-collapsible mw-collapsed wikitable"
  |  | 
 | ! c++11 for loop using lambda
  |  | 
 | |-
  |  | 
 | | This C++11 for loop is clean and elegant and a perfect way to check if your compiler is ready for c++11:
  |  | 
 |  vector<int> v;
  |  | 
 |  for_each( v.begin(), v.end(), [] (int val)
  |  | 
 |  {
  |  | 
 |     cout << val;
  |  | 
 |  } );
  |  | 
 | This is using a lambda function, we should switch from iterators and functors to those - but not quite yet, since we're writing cross-platform code.  Do not touch this until we can be sure that all platforms provide compatible C++11 handling.
  |  | 
 | |}
  |  | 
 | 
  |  | 
 | {| class="mw-collapsible mw-collapsed wikitable"
  |  | 
 | ! c++11 integer types
  |  | 
 | |-
  |  | 
 | | I really like the "fast" C++11 types, that give best performance for a guaranteed minimum bit width.  
  |  | 
 | Use them when you know a variable will not exceed the maximum value of that bit width, but does not have to be a precise bit width in memory or elsewhere.
  |  | 
 | 
  |  | 
 | Pick specific-width fields whenever data is shared with other processes and components and you want a guarantee of its bit width.
  |  | 
 | 
  |  | 
 | And when using pointer size and array indices you should use types defined for those specific situations.
  |  | 
 | 
  |  | 
 | FAST types:
  |  | 
 |     int_fast8_t
  |  | 
 |     int_fast16_t                fastest signed integer type with width of
  |  | 
 |     int_fast32_t                at least 8, 16, 32 and 64 bits respectively
  |  | 
 |     int_fast64_t
  |  | 
 | 
  |  | 
 |     uint_fast8_t
  |  | 
 |     uint_fast16_t               fastest unsigned integer type with width of
  |  | 
 |     uint_fast32_t               at least 8, 16, 32 and 64 bits respectively
  |  | 
 |     uint_fast64_t
  |  | 
 | SMALL types:
  |  | 
 |     int_least8_t
  |  | 
 |     int_least16_t               smallest signed integer type with width of
  |  | 
 |     int_least32_t               at least 8, 16, 32 and 64 bits respectively
  |  | 
 |     int_least64_t
  |  | 
 | 
  |  | 
 |     uint_least8_t
  |  | 
 |     uint_least16_t		smallest unsigned integer type with width of
  |  | 
 |     uint_least32_t		at least 8, 16, 32 and 64 bits respectively
  |  | 
 |     uint_least64_t
  |  | 
 | EXACT types:
  |  | 
 |     int8_t                      signed integer type with width of
  |  | 
 |     int16_t                     exactly 8, 16, 32 and 64 bits respectively
  |  | 
 |     int32_t                     with no padding bits and using 2's complement for negative values
  |  | 
 |     int64_t                     (provided only if the implementation directly supports the type)
  |  | 
 | 
  |  | 
 |     uint8_t                     unsigned integer type with width of
  |  | 
 |     uint16_t                    exactly 8, 16, 32 and 64 bits respectively
  |  | 
 |     uint32_t                    (provided only if the implementation directly supports the type)
  |  | 
 |     uint64_t
  |  | 
 | SPECIFIC-USE types:
  |  | 
 |     intptr_t                    integer type capable of holding a pointer
  |  | 
 |     uintptr_t                   unsigned integer type capable of holding a pointer 
  |  | 
 |     size_t                      unsigned integer type capable of holding an array index (same size as uintptr_t)
  |  | 
 | |}
  |  | 
 | 
  |  | 
 | {| class="mw-collapsible mw-collapsed wikitable"
  |  | 
 | ! C++11 scoped enumeration
  |  | 
 | |- 
  |  | 
 | | C++11 has scoped enumeration, which lets you specify the SPECIFIC VARIABLE TYPE for the enum.  Perfect, let's use uint_fast32_t.
  |  | 
 |  enum class STRING_PREF_INDEX int_fast32_t: { ... };
  |  | 
 | Unfortunately, gcc gives me a scary warning, and stuff fails.  For some reason, it does not know about the provided type, although it is definitely defined.  Revisit this later if you have time.
  |  | 
 |  warning: elaborated-type-specifier for a scoped enum must not use the ‘class’ keyword
  |  | 
 | Old skool is still cool:
  |  | 
 |  typedef enum
  |  | 
 |  {
  |  | 
 |      // assert( SP_COUNT == 2 );
  |  | 
 |      SP_FIRST = 0                ,
  |  | 
 |      SP_SOME_PREF = SP_FIRST     ,
  |  | 
 |      SP_ANOTHA                   ,
  |  | 
 |  
  |  | 
 |      SP_COUNT
  |  | 
 |  } STRING_PREF_INDEX;
  |  | 
 | |}
  |  | 
 | 
  |  | 
 | {| class="mw-collapsible mw-collapsed wikitable"  |  | {| class="mw-collapsible mw-collapsed wikitable"  | 
 | ! c++ in-memory storage of "major" objects  |  | ! c++ in-memory storage of "major" objects  | 
| Line 508: | 
Line 218: | 
 | -->  |  | -->  | 
 | {| class="mw-collapsible mw-collapsed wikitable"  |  | {| class="mw-collapsible mw-collapsed wikitable"  | 
 | ! C++  |  | ! c++11  | 
 | |-  |  | |-  | 
 | |  |  | |  | 
 | {| class="mw-collapsible mw-collapsed wikitable"
  |  | 
 | ! Deleting multiple elements in a collection
  |  | 
 | |-
  |  | 
 | | 
  |  | 
 | * For sequences (vector, list...), best practice is to use the [https://en.wikipedia.org/wiki/Erase%E2%80%93remove_idiom erase-remove] STL pattern
  |  | 
 | * For associative containers (set, map...): just recurse and remove iterators, they won't muck up the sequence.  [http://stackoverflow.com/questions/800955/remove-if-equivalent-for-stdmap example]
  |  | 
 | See MemoryModel::saveDirtyObjectsAsNeeded() for example code.
  |  | 
 | |}
  |  | 
 | {| class="mw-collapsible mw-collapsed wikitable"
  |  | 
 | ! c++ Create a portable C/C++ project
  |  | 
 | |-
  |  | 
 | | Use QtCreator + CMake, both available everywhere!
  |  | 
 |     set up:
  |  | 
 |         create a Qt project as: New Project-> Non-Qt/Plain C Project (CMake Build)
  |  | 
 |             pick the PARENT and use the name of the existing folder
  |  | 
 |             set up a build folder in the existing folder, called (base)/qtcreator-release-build
  |  | 
 |             it creates CMakeLists.txt (THIS IS BASICALLY THE PROJECT FILE!)
  |  | 
 |             also creates main.c or something
  |  | 
 |             build it!  make sure it works
  |  | 
 |             NOW we can edit CMakeLists.txt - change . to ./src to get it to scan the src folder for code!
  |  | 
 |             and easily add "known" libs!  this was all i needed:
  |  | 
 |                 TARGET_LINK_LIBRARIES(${PROJECT_NAME} pthread websockets)
  |  | 
 |             make sure it builds
  |  | 
 |             now we want a DEBUG build as well!
  |  | 
 |             Projects->Build&Run->pick Build in weird Build/Run pillbox->Edit build configs:
  |  | 
 |                 Rename: release
  |  | 
 |                 CMake build dir: Make sure build dir is set to release ie qtcreator-debug-build
  |  | 
 |                 Add: Clone: release, name: debug
  |  | 
 |                     for debug, add a custom build step BEFORE make step:
  |  | 
 |                         command: /usr/bin/cmake
  |  | 
 |                         args: -DCMAKE_BUILD_TYPE=Debug .
  |  | 
 |                         working dir: %{buildDir}
  |  | 
 |                         (add it, and move it up above make)
  |  | 
 |                         (build em both)
  |  | 
 |             Projects->Build&Run->pick Run in weird Build/Run pillbox
  |  | 
 |                 Run Configuration: rename to "{...} release"
  |  | 
 |                 clone it into "{...} debug"
  |  | 
 |                 change working dir to match Build path
  |  | 
 |                 change any needed params
  |  | 
 |     Now you should have build+run debug+release configurations, selectable in the weird project icon in bottom of left-side toolbar ("mode selector")
  |  | 
 | |}
  |  | 
 | {| class="mw-collapsible mw-collapsed wikitable"
  |  | 
 | ! boost release and debug build for linux
  |  | 
 | |-
  |  | 
 | |
  |  | 
 |     # download latest boost, eg: boost_1_59_0 
  |  | 
 |     m@wallee:~/development$ 7z x boost_1_59_0.7z
  |  | 
 |     cd boost_1_##_0
  |  | 
 |     build_boost_release_and_debug.sh
  |  | 
 |     # then patch .bashrc as instructed
  |  | 
 |     # eclipse and server/nix/bootstrap.sh are customized to match
  |  | 
 | To upgrade a project:
  |  | 
 |     cd nix
  |  | 
 |     make distclean  # removes nasty .deps folders that link to old boost if you let them
  |  | 
 |     make clean      # removes .o files etc
  |  | 
 |     cd ../build-Release && make distclean && make clean
  |  | 
 |     cd ../build-Debug && make distclean && make clean
  |  | 
 |     cd ..
  |  | 
 |     ./bootstrap force release
  |  | 
 |     ./bootstrap force debug
  |  | 
 | |}
  |  | 
 | {| class="mw-collapsible mw-collapsed wikitable"
  |  | 
 | ! boost release and debug build for Windows
  |  | 
 | |-
  |  | 
 | | Open a VS2015 x64 Native Tools Command Prompt.  
  |  | 
 | EITHER: for new installs, you have to run bootstrap.bat first, it will build b2; 
  |  | 
 | OR: for reruns, remove boost dirs: [bin.v2, stage].
  |  | 
 | Then build 64-bit:
  |  | 
 |  cd "....\boost_1_59_0"
  |  | 
 |  b2 toolset=msvc variant=release,debug link=static address-model=64
  |  | 
 |  rem trying to avoid excessive options, assuming I don't need these: threading=multi
  |  | 
 |  (old stuff)
  |  | 
 |        --toolset=msvc-14.0 address-model=64 --build-type=complete --stagedir=windows_lib\x64 stage
  |  | 
 |        Now open VS2013 x86 Native Tools Command Prompt and build 32-bit:
  |  | 
 |        cd "C:\Michael's Data\development\sixth_column\boost_1_55_0"
  |  | 
 |        bjam --toolset=msvc-12.0 address-model=32 --build-type=complete --stagedir=windows_lib\x86 stage
  |  | 
 | |}
  |  | 
 | {| class="mw-collapsible mw-collapsed wikitable"  |  | {| class="mw-collapsible mw-collapsed wikitable"  | 
 | ! c++11 include base constructor (etc) in derived class  |  | ! c++11 include base constructor (etc) in derived class  | 
| Line 840: | 
Line 473: | 
 |       SP_COUNT  |  |       SP_COUNT  | 
 |   } STRING_PREF_INDEX;  |  |   } STRING_PREF_INDEX;  | 
 | |}
  |  | 
 | 
  |  | 
 | {| class="mw-collapsible mw-collapsed wikitable"
  |  | 
 | ! c++ in-memory storage of "major" objects
  |  | 
 | |-
  |  | 
 | | 
  |  | 
 |     OBSERVATION ONE
  |  | 
 |  
  |  | 
 |     Consider An Important Qt Design: QObjects cannot normally be copied
  |  | 
 |         their copy constructors and assignment operators are private
  |  | 
 |         why?  A Qt Object...
  |  | 
 |             might have a unique QObject::objectName(). If we copy a Qt Object, what name should we give the copy?
  |  | 
 |             has a location in an object hierarchy. If we copy a Qt Object, where should the copy be located?
  |  | 
 |             can be connected to other Qt Objects to emit signals to them or to receive signals emitted by them. If we copy a Qt Object, how should we transfer these connections to the copy?
  |  | 
 |             can have new properties added to it at runtime that are not declared in the C++ class. If we copy a Qt Object, should the copy include the properties that were added to the original?
  |  | 
 |     in other words, a QObject is a pretty serious object that has the ability to be tied to other objects and resources in ways that make copying dangerous
  |  | 
 |     isn't this true of all serious objects?  pretty much
  |  | 
 | 
  |  | 
 |     OBSERVATION TWO
  |  | 
 |  
  |  | 
 |     if you have a vector of objects, you often want to track them individually outside the vector
  |  | 
 |     if you use a vector of pointers, you can move the object around much more cheaply, and not worry about costly large vector reallocations
  |  | 
 |     a vector of objects (not pointers) only makes sense if the number of objects is initially known and does not change over time
  |  | 
 | 
  |  | 
 |     OBSERVATION THREE
  |  | 
 |  
  |  | 
 |     STL vectors can store your pointers, iterate thru them, etc.
  |  | 
 |     for a vector of any substantial size, you want to keep objects sorted so you can find them quickly
  |  | 
 |     that's what my sorted_vector class is for; it simply bolts vector together with sort calls and a b_sorted status
  |  | 
 |     following STL practices, to get sorting, you have to provide operator< for whatever is in your vector
  |  | 
 |     BUT... you are not allowed to do operator<(const MyObjectPtr* right) because it would require a reference to a pointer which is not allowed
  |  | 
 |     BUT... you can provide a FUNCTOR to do the job, then provide it when sorting/searching
  |  | 
 |     a functor is basically a structure with a bool operator()(const MyObjectPtr* left, const MyObjectPtr* right)
  |  | 
 | 
  |  | 
 |     OBSERVATION FOUR
  |  | 
 |  
  |  | 
 |     unordered_set works even better when combining frequent CRUD with frequent lookups
  |  | 
 | 
  |  | 
 |     SUMMARY
  |  | 
 |     Dealing with tons of objects is par for the course in any significant app.
  |  | 
 |     Finding a needle in the haystack of those objects is also standard fare.
  |  | 
 |     Having multiple indices into those objects is also essential.
  |  | 
 |     Using unordered_set with object pointers and is very powerful.
  |  | 
 | |}
  |  | 
 | 
  |  | 
 | {| class="mw-collapsible mw-collapsed wikitable"
  |  | 
 | ! c++ stl reverse iterator skeleton
  |  | 
 | |-
  |  | 
 | | From [http://www.sgi.com/tech/stl/ReverseIterator.html SGI]...
  |  | 
 |  reverse_iterator rfirst(V.end());
  |  | 
 |  reverse_iterator rlast(V.begin());
  |  | 
 |  
  |  | 
 |  while (rfirst != rlast) 
  |  | 
 |  {
  |  | 
 |      cout << *rfirst << endl;
  |  | 
 |      ...
  |  | 
 |      rfirst++;
  |  | 
 |  }
  |  | 
 | |}
  |  | 
 | 
  |  | 
 | {| class="mw-collapsible mw-collapsed wikitable"
  |  | 
 | ! c++ stl reading a binary file into a string
  |  | 
 | |-
  |  | 
 | | 
  |  | 
 |     std::ifstream in("my.zip",std::ios::binary);
  |  | 
 |     if (!in)
  |  | 
 |     {
  |  | 
 |        std::cout << "problem with file open" << std::endl;
  |  | 
 |        return 0;
  |  | 
 |     }
  |  | 
 |     in.seekg(0,std::ios::end);
  |  | 
 |     unsigned long length = in.tellg();
  |  | 
 |     in.seekg(0,std::ios::beg);
  |  | 
 |   
  |  | 
 |     string str(length,0);
  |  | 
 |     std::copy( 
  |  | 
 |         std::istreambuf_iterator< char >(in) ,
  |  | 
 |         std::istreambuf_iterator< char >() ,
  |  | 
 |         str.begin() 
  |  | 
 |     );
  |  | 
 | 
  |  | 
 | For more, see [[Reading a binary file|c++ stl reading a binary file]]
  |  | 
 | |}
  |  | 
 | 
  |  | 
 | {| class="mw-collapsible mw-collapsed wikitable"
  |  | 
 | ! C/C++ best-in-class tool selection
  |  | 
 | |- 
  |  | 
 | | I need to have easy setup of debug-level tool support for portable C++11 code.  And I need to decide and stick to it to be efficient.
  |  | 
 | * '''Compiler selection'''
  |  | 
 | ** linux and mac: gcc
  |  | 
 | ** windows: Visual Studio
  |  | 
 | * '''IDE selection'''
  |  | 
 | ** linux and mac: Qt Creator
  |  | 
 | ** windows: Qt Creator (OR Visual Studio OR eclipse?)
  |  | 
 | * '''Debugger selection'''
  |  | 
 | ** linux and mac: Qt Creator
  |  | 
 | ** windows: Qt Creator (OR Visual Studio OR eclipse?)
  |  | 
 | |}  |  | |}  | 
 | |}  |  | |}  | 
| Line 947: | 
Line 483: | 
 | -->  |  | -->  | 
 | {| class="mw-collapsible mw-collapsed wikitable"  |  | {| class="mw-collapsible mw-collapsed wikitable"  | 
 | ! C++  |  | ! boost  | 
 | |-  |  | |-  | 
 | |  |  | |  | 
 | {| class="mw-collapsible mw-collapsed wikitable"
  |  | 
 | ! Deleting multiple elements in a collection
  |  | 
 | |-
  |  | 
 | | 
  |  | 
 | * For sequences (vector, list...), best practice is to use the [https://en.wikipedia.org/wiki/Erase%E2%80%93remove_idiom erase-remove] STL pattern
  |  | 
 | * For associative containers (set, map...): just recurse and remove iterators, they won't muck up the sequence.  [http://stackoverflow.com/questions/800955/remove-if-equivalent-for-stdmap example]
  |  | 
 | See MemoryModel::saveDirtyObjectsAsNeeded() for example code.
  |  | 
 | |}
  |  | 
 | {| class="mw-collapsible mw-collapsed wikitable"
  |  | 
 | ! c++ Create a portable C/C++ project
  |  | 
 | |-
  |  | 
 | | Use QtCreator + CMake, both available everywhere!
  |  | 
 |     set up:
  |  | 
 |         create a Qt project as: New Project-> Non-Qt/Plain C Project (CMake Build)
  |  | 
 |             pick the PARENT and use the name of the existing folder
  |  | 
 |             set up a build folder in the existing folder, called (base)/qtcreator-release-build
  |  | 
 |             it creates CMakeLists.txt (THIS IS BASICALLY THE PROJECT FILE!)
  |  | 
 |             also creates main.c or something
  |  | 
 |             build it!  make sure it works
  |  | 
 |             NOW we can edit CMakeLists.txt - change . to ./src to get it to scan the src folder for code!
  |  | 
 |             and easily add "known" libs!  this was all i needed:
  |  | 
 |                 TARGET_LINK_LIBRARIES(${PROJECT_NAME} pthread websockets)
  |  | 
 |             make sure it builds
  |  | 
 |             now we want a DEBUG build as well!
  |  | 
 |             Projects->Build&Run->pick Build in weird Build/Run pillbox->Edit build configs:
  |  | 
 |                 Rename: release
  |  | 
 |                 CMake build dir: Make sure build dir is set to release ie qtcreator-debug-build
  |  | 
 |                 Add: Clone: release, name: debug
  |  | 
 |                     for debug, add a custom build step BEFORE make step:
  |  | 
 |                         command: /usr/bin/cmake
  |  | 
 |                         args: -DCMAKE_BUILD_TYPE=Debug .
  |  | 
 |                         working dir: %{buildDir}
  |  | 
 |                         (add it, and move it up above make)
  |  | 
 |                         (build em both)
  |  | 
 |             Projects->Build&Run->pick Run in weird Build/Run pillbox
  |  | 
 |                 Run Configuration: rename to "{...} release"
  |  | 
 |                 clone it into "{...} debug"
  |  | 
 |                 change working dir to match Build path
  |  | 
 |                 change any needed params
  |  | 
 |     Now you should have build+run debug+release configurations, selectable in the weird project icon in bottom of left-side toolbar ("mode selector")
  |  | 
 | |}
  |  | 
 | {| class="mw-collapsible mw-collapsed wikitable"  |  | {| class="mw-collapsible mw-collapsed wikitable"  | 
 | ! boost release and debug build for linux  |  | ! boost release and debug build for linux  | 
| Line 1,028: | 
Line 523: | 
 | |}  |  | |}  | 
 | {| class="mw-collapsible mw-collapsed wikitable"  |  | {| class="mw-collapsible mw-collapsed wikitable"  | 
 | ! c++11 include base constructor (etc) in derived class  |  | ! boost regex (very similar to c++11, with LESS BUGS and MORE POWER)  | 
 | |-
  |  | 
 | | The awesome C++11 way to steal the constructor from the base class, oh man I've been waiting for this one...
  |  | 
 |   class HttpsServer : public Server<HTTPS>
  |  | 
 |   {
  |  | 
 |     // DOES THIS FOR YOU!
  |  | 
 |     /*
  |  | 
 |     HttpsServer(unsigned short port, size_t num_threads, const std::string& cert_file, const std::string& private_key_file)
  |  | 
 |     :
  |  | 
 |         // Call base class
  |  | 
 |         Server<HTTPS>::Server(port, num_threads, cert_file, private_key_file)
  |  | 
 |     {}
  |  | 
 |     */
  |  | 
 |     using Server<HTTPS>::Server;
  |  | 
 |     ....
  |  | 
 | |}
  |  | 
 | {| class="mw-collapsible mw-collapsed wikitable"
  |  | 
 | ! c++11 containers
  |  | 
 | |-
  |  | 
 | | sorted_vector || use when doing lots of unsorted insertions and maintaining constant sort would be expensive; vector is good for a big pile of things that only occasionally needs a sorted lookup
  |  | 
 | |-
  |  | 
 | | map || sorted binary search tree; always sorted by key; you can walk through in sorted order (choose unordered if not needed!)
  |  | 
 | |-
  |  | 
 | | multimap || same as map but allows dupe keys (not as common)
  |  | 
 | |-
  |  | 
 | | unordered_map || hashmap; always sorted by key; additional bucket required for hash collisions; no defined order when walking through
  |  | 
 | |-
  |  | 
 | | unordered_multimap || same as map but allows dupe keys; dupes are obviously in the same bucket, and you can walk just the dupes if needed
  |  | 
 | |-
  |  | 
 | | set<br>multiset<br>unordered_set<br>unordered_multiset || sets are just like maps, except the key is embedded in the object, nice for encapsulation.<br />
  |  | 
 | Items must be const (!) since they are the key - sounds bad, but this is mitigated by the mutable keyword.<br />
  |  | 
 | You can use mutable on the variables that are not part of the key to remove the const.<br />
  |  | 
 | This changes the constness of the object from binary (completely const) to logical (constness is defined by the developer).<br />
  |  | 
 | So... set is a good way to achieve both encapsulation and logical const - make const work for you, not against!  :-)<br />
  |  | 
 | |-
  |  | 
 | | set (etc.) of pointers || sets of pointers are the pinnacle of object stores<br />
  |  | 
 | The entire object can be dereferenced and accessed then without const issues.<br />
  |  | 
 | A pointer functor can be provided that does a sort by dereferencing the pointer to the object.<br />
  |  | 
 | Two requirements: you must make sure yourself that you do not change the key values - you can mark them const, provided in constructor;<br />
  |  | 
 | you must create sort/equal/hash functors that dereference the pointers to use object contents<br />
  |  | 
 | (the default will be by pointer address).<br />
  |  | 
 | The arguably biggest advantage, as a result, is that you can create multiple sets<br />
  |  | 
 | to reference the same group of objects with different sort funtors to create multiple indices.<br />
  |  | 
 | You just have to manage the keys carefully, so that they don't change (which would invalidate the sorting).<br />
  |  | 
 | The primary container can manage object allocation; using a heap-based unique_ptr allocation<br />
  |  | 
 |     map vs key redux
  |  | 
 |                 
  |  | 
 |         use a key in the set, derive a class from it with the contents
  |  | 
 |             + small key
  |  | 
 |             + encapsulation
  |  | 
 |             - requires mutable to solve the const problem
  |  | 
 |         use a key in the set, key includes a mutable object
  |  | 
 |             + encapsulation
  |  | 
 |             - weird bc everything uses a const object but we have const functions like save() that change the mutable subobject
  |  | 
 |         use a map
  |  | 
 |             + small key
  |  | 
 |             - no encapsulation, have to deal with a pair instead of an object
  |  | 
 |                 can we just put a ref to key in the value?  sure why not - err, bc we don't have access to it
  |  | 
 |             + solves const problem bc value is totally mutable by design
  |  | 
 |             + we can have multiple keys - and the value can have multiple refs to them
  |  | 
 |             + simpler equal and hash functions
  |  | 
 |         map:
  |  | 
 |             create an object with internal key(s)
  |  | 
 |             create map index(es) with duplicate key values outside the object - dupe data is the downside
  |  | 
 |         use set(s) with one static key for find(): 
  |  | 
 |             create an object with internal key(s)
  |  | 
 |             create set index(es) with specific hash/equals functor(s)
  |  | 
 |             when finding, use one static key object (even across indexes!) so there isn't a big construction each time; just set the necessary key values
  |  | 
 |                 that proves difficult when dealing with member vars that are references
  |  | 
 |                 but to solve it, just set up a structure of dummy static key objects that use each other; then provide a function to setKey(Object& keyref) { keyref_ = keyref; }
  |  | 
 |                 nope, can't reassign refs
  |  | 
 |                 the solution: use pointers not references
  |  | 
 |                 yes that's right
  |  | 
 |                 just do it
  |  | 
 |                 apparently there was a reason i was anti-reference for all those years
  |  | 
 |                 two reasons to use pointers:
  |  | 
 |                     dynamically allocated
  |  | 
 |                     reassignment required
  |  | 
 |                 there ya go.  simple.  get it done. 
  |  | 
 |             when accessing find results from the set, use a const_cast on the object!
  |  | 
 |             WARNING: a separate base class with the key sounds good... but fails when you have more than one index on the object.  just use a static key object for them all!
  |  | 
 |    |  | 
 | |}
  |  | 
 |    |  | 
 | {| class="mw-collapsible mw-collapsed wikitable"
  |  | 
 | ! c++11 example for large groups of objects with frequent crud AND search
  |  | 
 | |-
  |  | 
 | | Best solution is an unordered set of pointers:
  |  | 
 |  typedef boost::unordered_set<MajorObject*> MajorObjects;
  |  | 
 |    |  | 
 | |}
  |  | 
 |    |  | 
 | {| class="mw-collapsible mw-collapsed wikitable"
  |  | 
 | ! c++11 example for large groups of objects with infrequent crud and frequent search
  |  | 
 | |-
  |  | 
 | | Best solution is a vector of pointers sorted on demand (sorted_vector):
  |  | 
 |  TODO
  |  | 
 | |}
  |  | 
 |    |  | 
 | {| class="mw-collapsible mw-collapsed wikitable"
  |  | 
 | ! c++11 example to associate two complex objects (one the map key, one the map value)
  |  | 
 | |-
  |  | 
 | | Use unordered_map with a custom object as key.  You must add hash and equals functions.  Boost makes it easy:
  |  | 
 |  static bool operator==(MyKeyObject const& m1, MyKeyObject const& m2)
  |  | 
 |  {
  |  | 
 |      return 
  |  | 
 |              m1.id_0 == m2.id_0
  |  | 
 |          &&  m1.id_1 == m2.id_1;
  |  | 
 |  }
  |  | 
 |  static std::size_t hash_value(MyKeyObject const& mko)
  |  | 
 |  {
  |  | 
 |      std::size_t seed = 0;
  |  | 
 |      boost::hash_combine(seed, mko.id_0);
  |  | 
 |      boost::hash_combine(seed, mko.id_1);
  |  | 
 |      return seed;
  |  | 
 |  }
  |  | 
 |  typedef boost::unordered_map<MyKeyObject, MyValueObject*> MyMap;
  |  | 
 | Note that you can extend this to use a pointer to a key object, whoop.
  |  | 
 | |}
  |  | 
 |    |  | 
 | {| class="mw-collapsible mw-collapsed wikitable"
  |  | 
 | ! c++11 example for multiple unordered_set indexes into one group of objects
  |  | 
 | |-  |  | |-  | 
 | | Objects will be dynamically created.  One set should include them all and be responsible for memory allocation cleanup:  |  | | boost regex does everything you could need, take your time to get it right  | 
 |  TODO
  |  | * regex_search will work hard to find substrings, while regex_match requires your regex to match entire input  | 
 | |}
  |  | * smatch is a great way to get back a bunch of iterators to the results  | 
 |    |  | example:  | 
 | {| class="mw-collapsible mw-collapsed wikitable"
  |  |      virtual bool url_upgrade_any_old_semver(string& url)  | 
 | ! c++11 example for set with specific sorting
  |  | 
 | |-
  |  | 
 | | Use set with a specific sort functor.  You can create as many of these indexes as you want!
  |  | 
 |  struct customers_set_sort_functor
  |  | 
 |  {
  |  | 
 |      bool operator()(const MyObject* l, const MyObject* r) const
  |  | 
 |      {
  |  | 
 |          // the id is the key
  |  | 
 |          return l->id_ < r->id_;
  |  | 
 |      }
  |  | 
 |  };
  |  | 
 |  typedef set<MyObject*,myobject_sort_by_id_functor> MyObjectsById;
  |  | 
 | |}
  |  | 
 |    |  | 
 | {| class="mw-collapsible mw-collapsed wikitable"
  |  | 
 | ! c++11 loop through vector to erase some items
  |  | 
 | |-
  |  | 
 | | Note that other containers' iterators may not be invalidated so you can just erase() as needed...
  |  | 
 | For vectors, you have to play with iterators to get it right - watch for proper ++ pre/postfix!
  |  | 
 |  for (it = numbers.begin(); it != numbers.end(); )  // NOTE we increment below, only if we don't erase
  |  | 
 |  {
  |  | 
 |      if (*it.no_good()) 
  |  | 
 |      {
  |  | 
 |          numbers.erase(it++);  // NOTE that we ERASE THEN INCREMENT here.
  |  | 
 |      }
  |  | 
 |      else 
  |  | 
 |      {
  |  | 
 |          ++it;
  |  | 
 |      }
  |  | 
 |  }
  |  | 
 | I thought I had always looped backwards to do this, I *think* that's ok too, but I don't see it used in my code, I think I'll avoid.  :-)
  |  | 
 | |}
  |  | 
 |    |  | 
 | {| class="mw-collapsible mw-collapsed wikitable"
  |  | 
 | ! c++11 range based for loop, jacked with boost index if needed
  |  | 
 | |-
  |  | 
 | | No iterator usage at all.  Nice at times, not enough at others.  Make SURE to always use a reference or you will be working on a COPY.  Make it const if you aren't changing the object.
  |  | 
 |  for (auto& mc : my_container)
  |  | 
 |      mc.setString("default");
  |  | 
 |  for (const auto& cmc : my_container)
  |  | 
 |      cout << cmc.asString();
  |  | 
 | boost index can give you the index if you need it, sweet:
  |  | 
 |  #include <boost/range/adaptor/indexed.hpp>
  |  | 
 |  ...
  |  | 
 |  for (const auto &element: boost::adaptors::index(mah_container))
  |  | 
 |      cout << element.value() << element.index();
  |  | 
 | |}
  |  | 
 |    |  | 
 | {| class="mw-collapsible mw-collapsed wikitable"
  |  | 
 | ! c++11 for loop using lambda
  |  | 
 | |-
  |  | 
 | | This C++11 for loop is clean and elegant and a perfect way to check if your compiler is ready for c++11:
  |  | 
 |  vector<int> v;
  |  | 
 |  for_each( v.begin(), v.end(), [] (int val)
  |  | 
 |  {
  |  | 
 |     cout << val;
  |  | 
 |  } );
  |  | 
 | This is using a lambda function, we should switch from iterators and functors to those - but not quite yet, since we're writing cross-platform code.  Do not touch this until we can be sure that all platforms provide compatible C++11 handling.
  |  | 
 | |}
  |  | 
 |    |  | 
 | {| class="mw-collapsible mw-collapsed wikitable"
  |  | 
 | ! c++11 integer types
  |  | 
 | |-
  |  | 
 | | I really like the "fast" C++11 types, that give best performance for a guaranteed minimum bit width.  
  |  | 
 | Use them when you know a variable will not exceed the maximum value of that bit width, but does not have to be a precise bit width in memory or elsewhere.
  |  | 
 |    |  | 
 | Pick specific-width fields whenever data is shared with other processes and components and you want a guarantee of its bit width.
  |  | 
 |    |  | 
 | And when using pointer size and array indices you should use types defined for those specific situations.
  |  | 
 |    |  | 
 | FAST types:
  |  | 
 |      int_fast8_t  |  | 
 |     int_fast16_t                fastest signed integer type with width of
  |  | 
 |     int_fast32_t                at least 8, 16, 32 and 64 bits respectively
  |  | 
 |     int_fast64_t
  |  | 
 |    |  | 
 |     uint_fast8_t
  |  | 
 |     uint_fast16_t               fastest unsigned integer type with width of
  |  | 
 |     uint_fast32_t               at least 8, 16, 32 and 64 bits respectively
  |  | 
 |     uint_fast64_t
  |  | 
 | SMALL types:
  |  | 
 |     int_least8_t
  |  | 
 |     int_least16_t               smallest signed integer type with width of
  |  | 
 |     int_least32_t               at least 8, 16, 32 and 64 bits respectively
  |  | 
 |     int_least64_t
  |  | 
 |    |  | 
 |     uint_least8_t
  |  | 
 |     uint_least16_t		smallest unsigned integer type with width of
  |  | 
 |     uint_least32_t		at least 8, 16, 32 and 64 bits respectively
  |  | 
 |     uint_least64_t
  |  | 
 | EXACT types:
  |  | 
 |     int8_t                      signed integer type with width of
  |  | 
 |     int16_t                     exactly 8, 16, 32 and 64 bits respectively
  |  | 
 |     int32_t                     with no padding bits and using 2's complement for negative values
  |  | 
 |     int64_t                     (provided only if the implementation directly supports the type)
  |  | 
 |    |  | 
 |     uint8_t                     unsigned integer type with width of
  |  | 
 |     uint16_t                    exactly 8, 16, 32 and 64 bits respectively
  |  | 
 |     uint32_t                    (provided only if the implementation directly supports the type)
  |  | 
 |     uint64_t
  |  | 
 | SPECIFIC-USE types:
  |  | 
 |     intptr_t                    integer type capable of holding a pointer
  |  | 
 |     uintptr_t                   unsigned integer type capable of holding a pointer 
  |  | 
 |     size_t                      unsigned integer type capable of holding an array index (same size as uintptr_t)
  |  | 
 | |}
  |  | 
 |    |  | 
 | {| class="mw-collapsible mw-collapsed wikitable"
  |  | 
 | ! C++11 scoped enumeration
  |  | 
 | |- 
  |  | 
 | | C++11 has scoped enumeration, which lets you specify the SPECIFIC VARIABLE TYPE for the enum.  Perfect, let's use uint_fast32_t.
  |  | 
 |  enum class STRING_PREF_INDEX int_fast32_t: { ... };
  |  | 
 | Unfortunately, gcc gives me a scary warning, and stuff fails.  For some reason, it does not know about the provided type, although it is definitely defined.  Revisit this later if you have time.
  |  | 
 |  warning: elaborated-type-specifier for a scoped enum must not use the ‘class’ keyword
  |  | 
 | Old skool is still cool:
  |  | 
 |  typedef enum
  |  | 
 |  {
  |  | 
 |      // assert( SP_COUNT == 2 );
  |  | 
 |      SP_FIRST = 0                ,
  |  | 
 |      SP_SOME_PREF = SP_FIRST     ,
  |  | 
 |      SP_ANOTHA                   ,
  |  | 
 |  
  |  | 
 |      SP_COUNT
  |  | 
 |  } STRING_PREF_INDEX;
  |  | 
 | |}
  |  | 
 |    |  | 
 | {| class="mw-collapsible mw-collapsed wikitable"
  |  | 
 | ! c++ in-memory storage of "major" objects
  |  | 
 | |-
  |  | 
 | | 
  |  | 
 |     OBSERVATION ONE
  |  | 
 |  
  |  | 
 |     Consider An Important Qt Design: QObjects cannot normally be copied
  |  | 
 |         their copy constructors and assignment operators are private
  |  | 
 |         why?  A Qt Object...
  |  | 
 |             might have a unique QObject::objectName(). If we copy a Qt Object, what name should we give the copy?
  |  | 
 |             has a location in an object hierarchy. If we copy a Qt Object, where should the copy be located?
  |  | 
 |             can be connected to other Qt Objects to emit signals to them or to receive signals emitted by them. If we copy a Qt Object, how should we transfer these connections to the copy?
  |  | 
 |             can have new properties added to it at runtime that are not declared in the C++ class. If we copy a Qt Object, should the copy include the properties that were added to the original?
  |  | 
 |     in other words, a QObject is a pretty serious object that has the ability to be tied to other objects and resources in ways that make copying dangerous
  |  | 
 |     isn't this true of all serious objects?  pretty much
  |  | 
 |    |  | 
 |     OBSERVATION TWO
  |  | 
 |  
  |  | 
 |     if you have a vector of objects, you often want to track them individually outside the vector
  |  | 
 |     if you use a vector of pointers, you can move the object around much more cheaply, and not worry about costly large vector reallocations
  |  | 
 |     a vector of objects (not pointers) only makes sense if the number of objects is initially known and does not change over time
  |  | 
 |    |  | 
 |     OBSERVATION THREE
  |  | 
 |  
  |  | 
 |     STL vectors can store your pointers, iterate thru them, etc.
  |  | 
 |     for a vector of any substantial size, you want to keep objects sorted so you can find them quickly
  |  | 
 |     that's what my sorted_vector class is for; it simply bolts vector together with sort calls and a b_sorted status
  |  | 
 |     following STL practices, to get sorting, you have to provide operator< for whatever is in your vector
  |  | 
 |     BUT... you are not allowed to do operator<(const MyObjectPtr* right) because it would require a reference to a pointer which is not allowed
  |  | 
 |     BUT... you can provide a FUNCTOR to do the job, then provide it when sorting/searching
  |  | 
 |     a functor is basically a structure with a bool operator()(const MyObjectPtr* left, const MyObjectPtr* right)
  |  | 
 |    |  | 
 |     OBSERVATION FOUR
  |  | 
 |  
  |  | 
 |     unordered_set works even better when combining frequent CRUD with frequent lookups
  |  | 
 |    |  | 
 |     SUMMARY
  |  | 
 |     Dealing with tons of objects is par for the course in any significant app.
  |  | 
 |     Finding a needle in the haystack of those objects is also standard fare.
  |  | 
 |     Having multiple indices into those objects is also essential.
  |  | 
 |     Using unordered_set with object pointers and is very powerful.
  |  | 
 | |}
  |  | 
 |    |  | 
 | {| class="mw-collapsible mw-collapsed wikitable"
  |  | 
 | ! c++ stl reverse iterator skeleton
  |  | 
 | |-
  |  | 
 | | From [http://www.sgi.com/tech/stl/ReverseIterator.html SGI]...
  |  | 
 |  reverse_iterator rfirst(V.end());
  |  | 
 |  reverse_iterator rlast(V.begin());
  |  | 
 |  
  |  | 
 |  while (rfirst != rlast) 
  |  | 
 |  {
  |  | 
 |      cout << *rfirst << endl;
  |  | 
 |      ...
  |  | 
 |      rfirst++;
  |  | 
 |  }
  |  | 
 | |}
  |  | 
 |    |  | 
 | {| class="mw-collapsible mw-collapsed wikitable"
  |  | 
 | ! c++ stl reading a binary file into a string
  |  | 
 | |-
  |  | 
 | | 
  |  | 
 |     std::ifstream in("my.zip",std::ios::binary);
  |  | 
 |     if (!in)
  |  | 
 |      {  |  |      {  | 
 |        std::cout << "problem with file open" << std::endl;
  |  |       // Perform a regex to update the embedded version if needed.  | 
 |        return 0;
  |  |       // We have to see if (1) we have a semver and (2) it is not the current semver.  | 
 |  |       // Only then do we take action.  | 
 |  |       boost::regex regex("/([v0-9.]+?)/(.*)");  | 
 |  |       boost::smatch sm_res;  | 
 |  |       if (boost::regex_match(url,sm_res,regex,boost::match_default))  | 
 |  |       {  | 
 |  |         string incoming_semver(sm_res[1].first,sm_res[1].second);  | 
 |  |         if (incoming_semver != semanticVersion())  | 
 |  |         {  | 
 |  |           url = string("/")+semanticVersion()+"/"+string(sm_res[2].first,sm_res[2].second);  | 
 |  |           return true;  | 
 |  |         }        | 
 |  |       }  | 
 |  |       return false;  | 
 |      }  |  |      }  | 
 |     in.seekg(0,std::ios::end);
  |  | results:  | 
 |     unsigned long length = in.tellg();
  |  |       original string:    string(sm_res[0].first,sm_res[0].second);  | 
 |     in.seekg(0,std::ios::beg);
  |  |       first group:        string(sm_res[1].first,sm_res[1].second);  | 
 |   
  |  |       second group:       string(sm_res[2].first,sm_res[2].second);  | 
 |     string str(length,0);
  |  |       etc.  | 
 |     std::copy(  
  |  | 
 |         std::istreambuf_iterator< char >(in) ,
  |  | 
 |         std::istreambuf_iterator< char >() ,
  |  | 
 |         str.begin() 
  |  | 
 |     );
  |  | 
 |    |  | 
 | For more, see [[Reading a binary file|c++ stl reading a binary file]]
  |  | 
 | |}
  |  | 
 |    |  | 
 | {| class="mw-collapsible mw-collapsed wikitable"
  |  | 
 | ! C/C++ best-in-class tool selection
  |  | 
 | |- 
  |  | 
 | | I need to have easy setup of debug-level tool support for portable C++11 code.  And I need to decide and stick to it to be efficient.
  |  | 
 | * '''Compiler selection'''
  |  | 
 | ** linux and mac: gcc
  |  | 
 | ** windows: Visual Studio
  |  | 
 | * '''IDE selection'''
  |  | 
 | ** linux and mac: Qt Creator
  |  | 
 | ** windows: Qt Creator (OR Visual Studio OR eclipse?)
  |  | 
 | * '''Debugger selection'''
  |  | 
 | ** linux and mac: Qt Creator
  |  | 
 | ** windows: Qt Creator (OR Visual Studio OR eclipse?)
  |  | 
 | |}  |  | |}  | 
 | |}  |  | |}  |