User Manual
Here is a short user manual on how to use "dbj defval"
Option 2.2 and Option 3.
First please recall the top of this article. We are using GDI+ to add some dose of reality to these usage examples. And the dose of legacy code issues.
1 2 3 4 5 |
#include <windows.h> #include <objidl.h> #include <gdiplus.h> using namespace Gdiplus; #pragma comment(lib, "Gdiplus.lib") |
How to use Option 2.2
Declared by me as “probably a stunt” but of course, perfectly usable.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
// assume it is in the // dbj::v_two namespace using dbj::v_two::holder_maker; // here we are inside some (named) namespace // create process wide default values holders // creation happens on first call // GDI+ default smoothness inline auto default_smoot = dbj::v_two::holder_maker( SmoothingMode::SmoothingModeAntiAlias ); // GDI+ default linecap's inline auto default_lncap = dbj::v_two::holder_maker( LineCap::LineCapRound ); // just a default with inline auto default_width = dbj::v_two::holder_maker(10); inline void test_dbj_defval_option_two() { // just get the dflt width auto dw0 = default_width(); auto dw1 = default_width(); // somewhere and sometimes latter someone // might change the default value // here is how default_width(42); } |
You declare and define inside some namespace the global instances; after which callers from possible separate threads can use. Or change. I am sure you know how to make that “resilient in the presence of threads”.
How to use Option 3
note: c++ anonymous namespaces make variables inside them have internal linkage. I very rarely use them. Please do use named name space’s around these examples.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
// we assume: using namespace Gdiplus; // struct S final { // width holder a structure member mutable dbj::holder<REAL> width{ 0 }; // constructor changes the initial width S(REAL def_width) : width(def_width) {} }; // to test the const behaviour inline const S konst_{1024}; // initialized to 1024 // default process wide // smoothness using GDI+ enum's inline dbj::holder<SmoothingMode> smoothnes { SmoothingMode::SmoothingModeAntiAlias }; // default process wide // GDI+ line cap's inline dbj::holder<LineCap> linecap { LineCap::LineCapRound }; inline void test_dbj_defval_option_three() { // set the width to 512 for all the callers auto width_ = konst_.width(512); _ASSERTE(width_ == 512); const auto w1_ = konst_.width(); // 512 auto w2_ = konst_.width(); // 512 _ASSERTE( (w2_ == w1_) && (w2_ == width_) && (w1_ == width_) ); //use the previosuly declared // and instantiated def val holders auto lc_ = linecap(); auto sness = smoothnes(); } |
You declare and define dbj::holder<>
instances as (c++17) inline globals. Then every caller from some thread uses them. Please keep in mind calls above could be scattered across a few threads, but that would make the code longer and will obfuscate the usage pattern.
I hope you find this post useful and not difficult to grasp. Of course, there are many other solutions but the message is a simple one:
Simplicity rules
