layout: true name: blank styling: styling.css styling-by: Martin Weitzel .stylehint[ Styled with [{{styling}}]({{styling}}) by {{styling-by}} ] --- layout: true name: plain copyright: (CC) BY-SA branding: [Dipl.-Ing. Martin Weitzel](http://tbfe.de) customer: [for MicroConsult Training & Consulting GmbH](http://microconsult.de) {{header}} .pagefooter[ {{copyright}}: {{branding}} {{customer}} .microconsult-logo[] ] --- layout: true name: linkinfo copyright: (CC) BY-SA branding: [Dipl.-Ing. Martin Weitzel](http://tbfe.de) customer: [for MicroConsult Training & Consulting GmbH](http://microconsult.de) {{header}} .infographic[ [](InfoGraphics/{{graphic}}.png "Click to open – add [CTRL+] SHIFT for new [tabbed] window") ] .pagefooter[ {{copyright}}: {{branding}} {{customer}} .microconsult-logo[] ] --- layout: true name: withinfo copyright: (CC) BY-SA branding: [Dipl.-Ing. Martin Weitzel](http://tbfe.de) customer: [for MicroConsult Training & Consulting GmbH](http://microconsult.de) {{header}} .infolink.right[ [Click here for Info-Graphic {{graphic}}](InfoGraphics/{{graphic}}.png "add [CTRL+] SHIFT for own [tabbed] window") {{section}} ] .pagefooter[ {{copyright}}: {{branding}} {{customer}} .microconsult-logo[] ] --- template: blank name: frontmatter .title[ C++ Topics TKI ] .subtitle[ Monday: Augmented C++ Refresh Based On Three Code-Walks ] .author.pull-left[ Durchführung: Dipl.-Ing. Martin Weitzel Technische Beratung für EDV http://tbfe.de ] .client.pull-right[ Im Auftrag von: MicroConsult Training & Consulting GmbH http://www.microconsult.com ] --- template: plain class: agenda name: agenda header: ## Agenda This agenda and the following pages show a proposed path through the topics selected for the next two days. ------------------------------------------------------------------------------- * [Motivation ](#motivation) * [Abstract Data Types ](#abstract_data_types) ------------------------------------------------------------------------------- Variations and extensions can be agreed any time. --- template: plain name: motivation header: ### Motivation Consider lots of measurements that need to be monitored. .pull-left[ Each measurement is represented as floating point value … ``` float value; ``` ] .pull-right[ … but the sensor data is only valid when between certain limits: ``` float lowest; float highest; ``` ] Hence basically a processing like this is typically necessary: ``` if (value < lowest) { // use lowest } else if (value > highest) { // use highest } else { // use value } ``` --- template: plain name: motivation header: #### More Repeated Code … … may be necessary beyond this, like making decisions .pull-left[ Act on too low values … ``` if (value <= lowest) // whatever ``` ] .pull-right[ … or too high values: ``` if (value >= highest) // whatever ``` ] Also sometimes values need to be represented as a percentage between the lowest and the highest ``` const float range = highest - lowest; const float result = 100.0 * (value - lowest)/range; ``` Leading to the decision to pack data belonging together in a `struct`: ``` struct measurement { float lowest; float highest; float value; }; ``` --- template: plain name: abstract_data_types header: ### Abstract Data Types This struct is not only meant to exist for convenience but also to be **opaque** in the sense: .N[ A `struct measurement` is only to be accessed via dedicated functions. ] As in C all function names need to have unique names, * all functions meant to access it have the prefix `measurement_` * and take a pointer to a `struct measurement` as there first argument. Here are some of them (prototypes only): ``` float measurement_get_value(const struct measurement* const mp); void measurement_set_value(struct measurement* mp, const float v); float measurement_get_percent(const struct measurement* const mp); int measurement_is_low(const struct measurement* const mp); int measurement_is_high(const struct measurement* const mp); ``` --- template: plain name: internal_helpers header: ### Internal Helpers Also code that is required more than once can be packed that way, no matter whether it is meant to be used stand-alone:._[] ``` static float measurement_clamped(const struct measurement* const mp, const float v) { if (v < mp->lowest) return mp->lowest; if (v > mp->highest) return mp->highest; return v; } ``` .F[: The particular way in which this code is written was originally motivated to postpone the decision whether to do the "clamping" early or late. ] .N.center[ Further discussion will be based on the source `Example/ClampedValue/v0`. ] * [Header File](file:../Examples/ClampedValue/v0/measurement.h) * [Implementation](file:../Examples/ClampedValue/v0/measurement.c) * [Test Code](file:../Examples/ClampedValue/v0/measurement_test.cpp) * [Makefile](file:../Examples/ClampedValue/v0/Makefile) --- template: plain name: improving_c_with_classes header: ### Improving C With Classes The major feature of C++ – originally named *C with Classes* were: * Access Protection * Member Functions * Constructors * Member Initialization Lists * Overloading (Static Polymorphism) Furthermore some features of "Modern C++" are already used. * Uniform Initialization (aka. Brace Initialization) * `auto` as type for variables * `auto` as return type of functions .N.center[ Further discussion will be based on the source `Example/ClampedValue/v1`. ] * [Header File](file:../Examples/ClampedValue/v1/ClampedFloat.h) * [Implementation](file:../Examples/ClampedValue/v1/CmapedFloat.cpp) * [Test Code](file:../Examples/ClampedValue/v1/ClampedFloat_test.cpp) * [Makefile](file:../Examples/ClampedValue/v1/Makefile) --- template: plain name: details_of_clampedvalue_v2 header: ### Some Details On `Example/ClampedValue/v2` Now all the member functions are moved into the implementation file. * This is mostly done to show the syntax of member functions defined outside of classes. * It should be noted that `auto` as return type cannot any longer be used.._[] * Also it is more "fair" if you want to compare code size (and maybe speed) with the C version. .N.center[ Further discussion will be based on the source `Example/ClampedValue/v2`. ] * [Header File](file:../Examples/ClampedValue/v2/ClampedFloat.h) * [Implementation](file:../Examples/ClampedValue/v2/ClampedFloat.cpp) * [Test Code](file:../Examples/ClampedValue/v2/ClampedFloat_test.cpp) * [Makefile](file:../Examples/ClampedValue/v2/Makefile) .F[: What would be usable is the suffix return type syntax shown in a later example. ] --- template: plain name: details_of_clampedvalue_v3 header: ### Some Details On `Example/ClampedValue/v3` Some of the member functions are now moved back into the header file. * They are still defined outside of the class but as `inline` functions. * This is an alternative to writing the implementation into the class. * It makes it easier to move the functions from `inline` to non-`inline`. * Note that `auto` is still not usable as return type. .N.center[ Further discussion will be based on the source `Example/ClampedValue/v3`. ] * [Header File](file:../Examples/ClampedValue/v3/ClampedFloat.h) * [Implementation](file:../Examples/ClampedValue/v3/ClampedFloat.cpp) * [Test Code](file:../Examples/ClampedValue/v3/ClampedFloat_test.cpp) * [Makefile](file:../Examples/ClampedValue/v3/Makefile) --- template: plain name: details_of_clampedvalue_v4 header: ### Some Details On `Example/ClampedValue/v4` Moving the implementation of `inline` functions back into the class. * This enables the use of `auto` as return type. * For functions implemented as sub-routines in `ClampedFloat.cpp` the "trailing" or "suffix" return type syntax is shown. .N.center[ Further discussion will be based on the source `Example/ClampedValue/v4`. ] * [Header File](file:../Examples/ClampedValue/v4/ClampedFloat.h) * [Implementation](file:../Examples/ClampedValue/v4/ClampedFloat.cpp) * [Test Code](file:../Examples/ClampedValue/v4/ClampedFloat_test.cpp) * [Makefile](file:../Examples/ClampedValue/v4/Makefile) --- template: plain name: details_of_clampedvalue_v5 header: ### Some Details On `Example/ClampedValue/v5` To make the "Modern C++" features stand out a bit more, this version is rewound to only use what is available in C++98: * Only **classic initialization** syntax. * No direct member initialization. * No `auto` return types. * No constructor delegation. .N.center[ Further discussion will be based on the source `Example/ClampedValue/v5`. ] * [Header File](file:../Examples/ClampedValue/v5/ClampedFloat.h) * [Implementation](file:../Examples/ClampedValue/v5/ClampedFloat.cpp) * [Test Code](file:../Examples/ClampedValue/v5/ClampedFloat_test.cpp) * [Makefile](file:../Examples/ClampedValue/v5/Makefile) --- template: plain name: details_of_clampedvalue_v6 header: ### Some Details On `Example/ClampedValue/v6` This version turns the `ClampedFloat` class into `ClampedValue` template. * Note that there is still a function compiled separately. * There must be explicit template instantiations for every type used. * Otherwise a linker error will result. .N.center[ Further discussion will be based on the source `Example/ClampedValue/v6`. ] * [Header File](file:../Examples/ClampedValue/v6/ClampedValue.h) * [Implementation](file:../Examples/ClampedValue/v6/ClampedValue.cpp) * [Test Code](file:../Examples/ClampedValue/v6/ClampedValue_test.cpp) * [Makefile](file:../Examples/ClampedValue/v6/Makefile) --- template: plain name: details_of_clampedvalue_v7 header: ### Some Details On `Example/ClampedValue/v7` This version also moves the "true sub-routines back into the header file. * Therefore no explicit template instantiations will be required. * Note that no `inline` is to be used for the functions defined outside the class which should be compiled as sub-routines. .N.center[ Further discussion will be based on the source `Example/ClampedValue/v7`. ] * [Header File](file:../Examples/ClampedValue/v7/ClampedValue.h) * [Implementation](file:../Examples/ClampedValue/v7/ClampedValue.cpp) * [Test Code](file:../Examples/ClampedValue/v7/ClampedFloat_test.cpp) * [Makefile](file:../Examples/ClampedValue/v7/Makefile) --- template: plain name: details_of_clampedvalue_v8 header: ### Some Details On `Example/ClampedValue/v8` For further discussion (performance and robustness issues) and later improvements. .N.center[ Further discussion will be based on the source `Example/ClampedValue/v8`. ] * [Header File](file:../Examples/ClampedValue/v8/ClampedValue.h) * [Test Code](file:../Examples/ClampedValue/v8/ClampedValue_test.cpp) * [Makefile](file:../Examples/ClampedValue/v8/Makefile) --- template: plain header: ### And Now for Something Completely Different "Variable which know their name" (when written to an `std::ostream`) and "variables registering themselves to be reset" (from anywhere, any time), demonstrating * use of `std::ostream` * overloading of `operator<<` * static member variable and functions * and again: .N.center[ Generic Programming with Templates. ] --- template: plain name: details_of_namedvalue_v0 `Example/NamedValue/v0` header: ### Some Details on the `NamedFloat`-Example .N.center[ Further discussion will be based on the source `Example/NamedValue/v0`. ] * [Header File](file:../Examples/NamedValue/v0/NamedFloat.h) * [Test Code](file:../Examples/NamedValue/v0/NamedFloat_test.cpp) * [Makefile](file:../Examples/NamedValue/v0/Makefile) --- template: plain name: details_of_namedvalue_v1 header: ### Some Details on the `NamedValue`-Example .N.center[ Further discussion will be based on the source `Example/NamedValue/v01` ] * [Header File](file:../Examples/NamedValue/v1/NamedValue.h) * [Test Code](file:../Examples/NamedValue/v1/NamedValue_test.cpp) * [Makefile](file:../Examples/NamedValue/v1/Makefile) --- template: plain name: details_of_resettable_v0 header: ### Some Details on the `Resettable`-Example .N.center[ Further discussion will be based on the source `Example/Resettable/v0` ] * [Header File](file:../Examples/Resettable/v0/Resettable.h) * [Test Code](file:../Examples/Resettable/v0/Resettable_test.cpp) * [Makefile](file:../Examples/Resettable/v0/Makefile)