diff --git a/content/programming.tree b/content/programming.tree index e66275a..ff4963a 100644 --- a/content/programming.tree +++ b/content/programming.tree @@ -7,6 +7,12 @@ % id = "programming/projects" + ## projects + - (actually nothing here yet lol, I was about to write something here but forgot but now don't wanna delete a branch I'm gonna bring back again anyways) + +% content.link = "programming/cxx" + id = "programming/cxx" ++ ## C++ + % content.link = "programming/unreal-engine" id = "programming/unreal-engine" + ## Unreal Engine diff --git a/content/programming/cxx.tree b/content/programming/cxx.tree new file mode 100644 index 0000000..ebd3c84 --- /dev/null +++ b/content/programming/cxx.tree @@ -0,0 +1,45 @@ +- design lessons from the best programming language of all time that everyone loves (not really) + ++ access modifiers as labels (`private:`, `protected:`, and `public:`) + + - although Java and C#'s approach to symbol privacy may be verbose, it has one great advantage: it is stateless. + + - the way they're implemented in C++, it's essentially a bit more parsing state you have to keep track of + + - and you know what other parsing state you have to keep track of in C++? - that's right, the preprocessor.\ + access modifiers, like all tokens, are affected by the preprocessor, and you have to take that into account + + - take the following example: + ```cpp + class ComfyZone + { + std::vector _soft_beds; + + #if ENABLE_HUGS + + public: + void hug(Person& person); + + #endif + + int _remaining_hugs = 10; + }; + ``` + + - although quite contrived, it illustrates the problem pretty well + + - (before you ask, `_remaining_hugs` needs to be always present because it has to be (de)serialized no matter if hugging functionality is compiled in. otherwise we'd get data loss.) + + - we intended for `_remaining_hugs` to be private, but if hugs are enabled, it becomes public. + + - this can be _very_ hard to spot if you have a big class with lots of declarations inside. + + - this can be worked around by banning access modifiers from appearing in `#ifdef`s, but you have to *realize* that this might happen + + - and I've seen instances of this exact thing occurring in the Unreal Engine codebase, which is *full* of long lists of declarations (made even longer by the prevalence of `UPROPERTY()`s) + + - even if we didn't have the preprocessor, that access modifier is state _you_ have to keep track of + + - I very often find myself needing to scroll upward after Ctrl-clicking on a field or function declaration, just to find out if I can use it + + - (thankfully IDEs are helpful here and Rider shows you a symbol's visibility in the tooltip on hover, but I don't have Rider on code reviews)