Development reference: Difference between revisions
No edit summary  | 
				No edit summary  | 
				||
| Line 499: | Line 499: | ||
** windows: Qt Creator (OR Visual Studio OR eclipse?)  | ** windows: Qt Creator (OR Visual Studio OR eclipse?)  | ||
|}  | |}  | ||
|}  | |||
<!--   | |||
===========================================================================================================================================================================================================================================================================================  | |||
-->  | |||
{| class="mw-collapsible mw-collapsed wikitable"  | |||
! C++  | |||
|-  | |||
|  | |||
{| 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"  | |||
! 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"  | |||
! 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?)  | |||
|}  | |||
|}  | |||
<!--   | |||
===========================================================================================================================================================================================================================================================================================  | |||
-->  | |||
{| class="mw-collapsible mw-collapsed wikitable"  | |||
! C++  | |||
|-  | |||
|  | |||
{| 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"  | |||
! 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"  | {| 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;  | |||
       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 626: | Line 1,485: | ||
     at first i thought this would work: /usr/local/lib  |      at first i thought this would work: /usr/local/lib  | ||
     but i did a static build so i needed teh actual exe!  COOL  |      but i did a static build so i needed teh actual exe!  COOL  | ||
|}  | |||
{| class="mw-collapsible mw-collapsed wikitable"  | |||
! c/c++ gdb debugging  | |||
|-   | |||
|   | |||
 (gdb) help break  | |||
 Set breakpoint at specified line or function.  | |||
 Argument may be line number, function name, or "*" and an address.  | |||
 If line number is specified, break at start of code for that line.  | |||
 If function is specified, break at start of code for that function.  | |||
 If an address is specified, break at that exact address.  | |||
 With no arg, uses current execution address of selected stack frame.  | |||
 This is useful for breaking on return to a stack frame.  | |||
 Multiple breakpoints at one place are permitted, and useful if conditional.      | |||
 Do "help breakpoints" for info on other commands dealing with breakpoints.  | |||
|- 		  | |||
| ddd gives you a front end.  I need to use it more, compare to other options  | |||
|}  | |}  | ||
|}  | |}  | ||
Revision as of 01:41, 8 June 2017
Design, programming and version control.
| Patterns | |||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
 
 
 
 
 
 
 
 
  | 
| C++ | |||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
  | 
| C++ | |||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
  | 
| C++ | |||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
  | 
| C++ libraries | 
|---|
| C/C++ building/linking | ||||
|---|---|---|---|---|
 
  | 
| C/C++ debugging | |||||
|---|---|---|---|---|---|
 
  | 
| C | ||||
|---|---|---|---|---|
 
  | 
| Bootstrap | ||||||||
|---|---|---|---|---|---|---|---|---|
 
 
 
  | 
| D3 | ||||
|---|---|---|---|---|
 
  | 
| RESTFul http | ||
|---|---|---|
  | 
| Javascript and JQuery | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|
 
 
 
 
  | 
| Node.js | ||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
 
 
 
 
 
 
 
  | 
| css | 
|---|
 /* class="first second" */
 .first.second {}
 /* class="first" OR class="second" */
 .first, .second {}
 /* class="first second", or class="second", or class="third second", or class="second third" */
 .second {}
 /* apply to any .child at any depth under .parent */
 .parent .child {}
 /* apply to .child if it is DIRECTLY under .parent */
 .parent > .child {}
 | 
| SQL | ||
|---|---|---|
  | 
| Java | 
|---|
| Scala | 
|---|
| PHP | |||
|---|---|---|---|
  | 
| git | 
|---|
| misc | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|
 
 
 
 
 
  |