{
"$type": "site.standard.document",
"description": "Sensible defaults for a very irrational language.",
"path": "/posts/cpp-prelude/",
"publishedAt": "2024-01-08T22:04:59.000Z",
"site": "at://did:plc:6n2ngs7zpcpwxz3jaoxj56tu/site.standard.publication/3mo6y7ludvn2h",
"tags": [
"programming",
"computer science"
],
"textContent": "Modern C++ makes me sad when I look at it. So this is my attempt to change\nseveral of the defaults we use to code in C++. Additionally, several features\nthat are missing in the language (but enabled through obscure compiler macros\nand directives) are enabled.\n\nproject page\n\nIncludes\nSeveral containers and algorithms can be included using the or\n or directive. I use these very frequently, others might not. For that\nreason they are opt-in. To enable them define the the containers or algorithms\ndirective before including the header.\n\nLike this:\n\nThe following containers are included:\n - unordered_map\n - unordered_set\n - queue\n - stack\n - list\n - span\n\nThe following algorithms are included:\n - algorithm\n - ranges\n - numeric\n\n The following io headers are included:\n - format\n - fstream\n\nThe following headers are included by default:\n - cstdint\n - limits.h\n - iostream\n\nTypes\nA mix of the naming scheme in Rust and HolyC is very aesthetically pleasing.\nTypes become terse with only the information you need at a first glance.\nFurthermore, for consistency, all types should begin with capital letters.\n\nNumeric Types\n\nFloats\nMost of the floating types that are mentioned in IEEE 754.\n| Prelude | Vanilla |\n|-----------|---------|\n| | N/A |\n| | N/A |\n| | |\n| | N/A |\n| | |\n| | N/A |\n| | N/A or |\n| | N/A |\n| | N/A |\n\nAdditional information on the brain floating data type.\n\n| Prelude | Vanilla |\n|-----------|---------|\n| | |\n| | N/A |\n| | |\n| | |\n| | |\n| | |\n| | N/A |\n| | |\n| | |\n| | |\n| | |\n| | N/A |\n\nThese changes beg the question: What is wrong with ?\nWell would be a perfectly valid type if C++ supported Big Integers like\nJava does. The problem is is fixed to a type that is sometimes 32-bits\nand other times something else. I think this is very inelegant and needlessly\nterse. It is better to simply know what kind of integer and bit-width it takes\nup.\n\nThe only exception to this rule being and . For the former we want\nto preserve the ability to scale depending on what system runs the binary. For\nthe latter we want to optimize the CI development cycle, so the less worries the\nbetter. If you want an then have an .\n\nOther Types\n| Prelude | Vanilla |\n|-----------|---------|\n| | |\n| | N/A |\n| | |\n| | |\n| | |\n| | |\n| | |\n| | |\n| | |\n\nIn most situations, it is clearer to write the type as a than a .\nSame goes for .\nThis also remains consistent with the implementation of smart pointers in the\nstandard library, for example .\n\n are enabled by default.\n\nKeywords\n| Prelude | Vanilla |\n|-----------|---------|\n| | |\n| | |\n| | |\n| | |\n| | |\n| | |\n| | |\n| | |\n\nYou define terms as . If you need the term to be of any specific\nnumeric type then use suffixes like: (x is unsigned).\nIf you need a variable term then use the keyword instead. The motivation\nfor this is that you should prefer immutable terms before considering mutable\nvariables.\n\nAll functions should be and be annotated with trailing return\ntypes.\nIf you need to ignore the return value of a function then use to\nexplicitly ignore it.\nAdditionally, the term (function) should be used in its most literal\nmathematical sense, for a given input it will always produce the same output.\nIf you want to do something that requires side effects then use the \n(procedure) keyword instead.\n\n, and naming conventions are taken from Haskell. The motivation\nbeing that is extremely verbose for accessing the\nfirst/second/third/etc members of that tuple.\n\nBetter Main\nThe way is defined for use is very old. It is not type safe and uses old\ntypes like c-strings. We can, instead, make a better that is the one we\ndefine our program in and forward the arguments in a type-safe manner.\n\nImplementation taken from C++ Weekly ep 361 by Jason Turner\n\nNOTE: It has been mentioned that has historically been used for passing\nsensitive information like passwords to programs. In that case, the array used\nto store the different arguments is chopped up to remove the sensitive\ninformation. For now, this method does not allow do that. Furthermore,\nsending sensitive information through command line arguments is a bad idea IMO.\n\nShort example\nSolution for Rosetta Code \"Balanced Brackets\"\nusing this prelude.\n\nTODO:\n- [ ] Add algorithms\n- [ ] Improve range algorithms",
"title": "C++ Prelude"
}