1932aae77SSourabh Singh Tomar<!--===- docs/C++style.md 2932aae77SSourabh Singh Tomar 3932aae77SSourabh Singh Tomar Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4932aae77SSourabh Singh Tomar See https://llvm.org/LICENSE.txt for license information. 5932aae77SSourabh Singh Tomar SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6932aae77SSourabh Singh Tomar 7932aae77SSourabh Singh Tomar--> 8932aae77SSourabh Singh Tomar 9271a7bb1SRichard Barton# Flang C++ Style Guide 10271a7bb1SRichard Barton 11*b7ff0320Scor3ntin```{contents} 12*b7ff0320Scor3ntin--- 13*b7ff0320Scor3ntinlocal: 14*b7ff0320Scor3ntin--- 15271a7bb1SRichard Barton``` 16271a7bb1SRichard Barton 17271a7bb1SRichard BartonThis document captures the style guide rules that are followed in the Flang codebase. 18271a7bb1SRichard Barton 19eaff2004Ssameeran joshi## In brief: 20eaff2004Ssameeran joshi* Use *clang-format* 21eaff2004Ssameeran joshifrom llvm 7 22eaff2004Ssameeran joshion all C++ source and header files before 23b90eef30SQuinn Phamevery merge to main. All code layout should be determined 24eaff2004Ssameeran joshiby means of clang-format. 25eaff2004Ssameeran joshi* Where a clear precedent exists in the project, follow it. 26eaff2004Ssameeran joshi* Otherwise, where [LLVM's C++ style guide](https://llvm.org/docs/CodingStandards.html#style-issues) 27eaff2004Ssameeran joshiis clear on usage, follow it. 28eaff2004Ssameeran joshi* Otherwise, where a good public C++ style guide is relevant and clear, 29eaff2004Ssameeran joshi follow it. [Google's](https://google.github.io/styleguide/cppguide.html) 30eaff2004Ssameeran joshi is pretty good and comes with lots of justifications for its rules. 31eaff2004Ssameeran joshi* Reasonable exceptions to these guidelines can be made. 32eaff2004Ssameeran joshi* Be aware of some workarounds for known issues in older C++ compilers that should 33eaff2004Ssameeran joshi still be able to compile f18. They are listed at the end of this document. 34eaff2004Ssameeran joshi 35eaff2004Ssameeran joshi## In particular: 36eaff2004Ssameeran joshi 37eaff2004Ssameeran joshiUse serial commas in comments, error messages, and documentation 38eaff2004Ssameeran joshiunless they introduce ambiguity. 39eaff2004Ssameeran joshi 40eaff2004Ssameeran joshi### Error messages 41eaff2004Ssameeran joshi1. Messages should be a single sentence with few exceptions. 42eaff2004Ssameeran joshi1. Fortran keywords should appear in upper case. 43eaff2004Ssameeran joshi1. Names from the program appear in single quotes. 44eaff2004Ssameeran joshi1. Messages should start with a capital letter. 45eaff2004Ssameeran joshi1. Messages should not end with a period. 46eaff2004Ssameeran joshi 47eaff2004Ssameeran joshi### Files 48eaff2004Ssameeran joshi1. File names should use dashes, not underscores. C++ sources have the 49eaff2004Ssameeran joshiextension ".cpp", not ".C" or ".cc" or ".cxx". Don't create needless 50eaff2004Ssameeran joshisource directory hierarchies. 51eaff2004Ssameeran joshi1. Header files should be idempotent. Use the usual technique: 52eaff2004Ssameeran joshi``` 53eaff2004Ssameeran joshi#ifndef FORTRAN_header_H_ 54eaff2004Ssameeran joshi#define FORTRAN_header_H_ 55eaff2004Ssameeran joshi// code 56eaff2004Ssameeran joshi#endif // FORTRAN_header_H_ 57eaff2004Ssameeran joshi``` 58eaff2004Ssameeran joshi1. `#include` every header defining an entity that your project header or source 59eaff2004Ssameeran joshifile actually uses directly. (Exception: when foo.cpp starts, as it should, 60eaff2004Ssameeran joshiwith `#include "foo.h"`, and foo.h includes bar.h in order to define the 61eaff2004Ssameeran joshiinterface to the module foo, you don't have to redundantly `#include "bar.h"` 62eaff2004Ssameeran joshiin foo.cpp.) 63eaff2004Ssameeran joshi1. In the source file "foo.cpp", put its corresponding `#include "foo.h"` 64eaff2004Ssameeran joshifirst in the sequence of inclusions. 65eaff2004Ssameeran joshiThen `#include` other project headers in alphabetic order; then C++ standard 66eaff2004Ssameeran joshiheaders, also alphabetically; then C and system headers. 67eaff2004Ssameeran joshi1. Don't use `#include <iostream>`. If you need it for temporary debugging, 68eaff2004Ssameeran joshiremove the inclusion before committing. 69eaff2004Ssameeran joshi 70eaff2004Ssameeran joshi### Naming 71eaff2004Ssameeran joshi1. C++ names that correspond to well-known interfaces from the STL, LLVM, 72eaff2004Ssameeran joshiand Fortran standard 73eaff2004Ssameeran joshican and should look like their models when the reader can safely assume that 74eaff2004Ssameeran joshithey mean the same thing -- e.g., `clear()` and `size()` member functions 75eaff2004Ssameeran joshiin a class that implements an STL-ish container. 76eaff2004Ssameeran joshiFortran intrinsic function names are conventionally in ALL CAPS. 77eaff2004Ssameeran joshi1. Non-public data members should be named with leading miniscule (lower-case) 78eaff2004Ssameeran joshiletters, internal camelCase capitalization, and a trailing underscore, 79eaff2004Ssameeran joshie.g. `DoubleEntryBookkeepingSystem myLedger_;`. POD structures with 80eaff2004Ssameeran joshionly public data members shouldn't use trailing underscores, since they 81eaff2004Ssameeran joshidon't have class functions from which data members need to be distinguishable. 82eaff2004Ssameeran joshi1. Accessor member functions are named with the non-public data member's name, 83eaff2004Ssameeran joshiless the trailing underscore. Mutator member functions are named `set_...` 84eaff2004Ssameeran joshiand should return `*this`. Don't define accessors or mutators needlessly. 85eaff2004Ssameeran joshi1. Other class functions should be named with leading capital letters, 86eaff2004Ssameeran joshiCamelCase, and no underscores, and, like all functions, should be based 87eaff2004Ssameeran joshion imperative verbs, e.g. `HaltAndCatchFire()`. 88eaff2004Ssameeran joshi1. It is fine to use short names for local variables with limited scopes, 89eaff2004Ssameeran joshiespecially when you can declare them directly in a `for()`/`while()`/`if()` 90eaff2004Ssameeran joshicondition. Otherwise, prefer complete English words to abbreviations 91eaff2004Ssameeran joshiwhen creating names. 92eaff2004Ssameeran joshi 93eaff2004Ssameeran joshi### Commentary 94eaff2004Ssameeran joshi1. Use `//` for all comments except for short `/*notes*/` within expressions. 95eaff2004Ssameeran joshi1. When `//` follows code on a line, precede it with two spaces. 96eaff2004Ssameeran joshi1. Comments should matter. Assume that the reader knows current C++ at least as 97eaff2004Ssameeran joshiwell as you do and avoid distracting her by calling out usage of new 98eaff2004Ssameeran joshifeatures in comments. 99eaff2004Ssameeran joshi 100eaff2004Ssameeran joshi### Layout 101eaff2004Ssameeran joshiAlways run `clang-format` on your changes before committing code. LLVM 102eaff2004Ssameeran joshihas a `git-clang-format` script to facilitate running clang-format only 103eaff2004Ssameeran joshion the lines that have changed. 104eaff2004Ssameeran joshi 105eaff2004Ssameeran joshiHere's what you can expect to see `clang-format` do: 106eaff2004Ssameeran joshi1. Indent with two spaces. 107eaff2004Ssameeran joshi1. Don't indent public:, protected:, and private: 108eaff2004Ssameeran joshiaccessibility labels. 109eaff2004Ssameeran joshi1. Never use more than 80 characters per source line. 110eaff2004Ssameeran joshi1. Don't use tabs. 111eaff2004Ssameeran joshi1. Don't indent the bodies of namespaces, even when nested. 112eaff2004Ssameeran joshi1. Function result types go on the same line as the function and argument 113eaff2004Ssameeran joshinames. 114eaff2004Ssameeran joshi 115eaff2004Ssameeran joshiDon't try to make columns of variable names or comments 116eaff2004Ssameeran joshialign vertically -- they are maintenance problems. 117eaff2004Ssameeran joshi 118eaff2004Ssameeran joshiAlways wrap the bodies of `if()`, `else`, `while()`, `for()`, `do`, &c. 11945cd405dSDiana Picuswith braces, even when the body is a single statement or empty. Note that this 12045cd405dSDiana Picusdiverges from the LLVM coding style. In parts of the codebase that make heavy 12145cd405dSDiana Picususe of LLVM or MLIR APIs (e.g. the Lower and Optimizer libraries), use the 12245cd405dSDiana PicusLLVM style instead. The 123eaff2004Ssameeran joshiopening `{` goes on 124eaff2004Ssameeran joshithe end of the line, not on the next line. Functions also put the opening 125eaff2004Ssameeran joshi`{` after the formal arguments or new-style result type, not on the next 126eaff2004Ssameeran joshiline. Use `{}` for empty inline constructors and destructors in classes. 127eaff2004Ssameeran joshi 128eaff2004Ssameeran joshiIf any branch of an `if`/`else if`/`else` cascade ends with a return statement, 129eaff2004Ssameeran joshithey all should, with the understanding that the cases are all unexceptional. 130eaff2004Ssameeran joshiWhen testing for an error case that should cause an early return, do so with 131eaff2004Ssameeran joshian `if` that doesn't have a following `else`. 132eaff2004Ssameeran joshi 133eaff2004Ssameeran joshiDon't waste space on the screen with needless blank lines or elaborate block 134eaff2004Ssameeran joshicommentary (lines of dashes, boxes of asterisks, &c.). Write code so as to be 135eaff2004Ssameeran joshieasily read and understood with a minimum of scrolling. 136eaff2004Ssameeran joshi 137eaff2004Ssameeran joshiAvoid using assignments in controlling expressions of `if()` &c., even with 138eaff2004Ssameeran joshithe idiom of wrapping them with extra parentheses. 139eaff2004Ssameeran joshi 140eaff2004Ssameeran joshiIn multi-element initializer lists (especially `common::visitors{...}`), 141eaff2004Ssameeran joshiincluding a comma after the last element often causes `clang-format` to do 142eaff2004Ssameeran joshia better jobs of formatting. 143eaff2004Ssameeran joshi 144eaff2004Ssameeran joshi### C++ language 145eaff2004Ssameeran joshiUse *C++17*, unless some compiler to which we must be portable lacks a feature 146eaff2004Ssameeran joshiyou are considering. 147eaff2004Ssameeran joshiHowever: 148eaff2004Ssameeran joshi1. Never throw or catch exceptions. 149eaff2004Ssameeran joshi1. Never use run-time type information or `dynamic_cast<>`. 150eaff2004Ssameeran joshi1. Never declare static data that executes a constructor. 151eaff2004Ssameeran joshi (This is why `#include <iostream>` is contraindicated.) 152eaff2004Ssameeran joshi1. Use `{braced initializers}` in all circumstances where they work, including 153eaff2004Ssameeran joshidefault data member initialization. They inhibit implicit truncation. 154eaff2004Ssameeran joshiDon't use `= expr` initialization just to effect implicit truncation; 155eaff2004Ssameeran joshiprefer an explicit `static_cast<>`. 156eaff2004Ssameeran joshiWith C++17, braced initializers work fine with `auto` too. 157eaff2004Ssameeran joshiSometimes, however, there are better alternatives to empty braces; 158eaff2004Ssameeran joshie.g., prefer `return std::nullopt;` to `return {};` to make it more clear 159eaff2004Ssameeran joshithat the function's result type is a `std::optional<>`. 160eaff2004Ssameeran joshi1. Avoid unsigned types apart from `size_t`, which must be used with care. 161eaff2004Ssameeran joshiWhen `int` just obviously works, just use `int`. When you need something 162eaff2004Ssameeran joshibigger than `int`, use `std::int64_t` rather than `long` or `long long`. 163eaff2004Ssameeran joshi1. Use namespaces to avoid conflicts with client code. Use one top-level 164eaff2004Ssameeran joshi`Fortran` project namespace. Don't introduce needless nested namespaces within the 165eaff2004Ssameeran joshiproject when names don't conflict or better solutions exist. Never use 166eaff2004Ssameeran joshi`using namespace ...;` outside test code; never use `using namespace std;` 167eaff2004Ssameeran joshianywhere. Access STL entities with names like `std::unique_ptr<>`, 168eaff2004Ssameeran joshiwithout a leading `::`. 169eaff2004Ssameeran joshi1. Prefer `static` functions over functions in anonymous namespaces in source files. 170eaff2004Ssameeran joshi1. Use `auto` judiciously. When the type of a local variable is known, 171eaff2004Ssameeran joshimonomorphic, and easy to type, be explicit rather than using `auto`. 172eaff2004Ssameeran joshiDon't use `auto` functions unless the type of the result of an outlined member 173eaff2004Ssameeran joshifunction definition can be more clear due to its use of types declared in the 174eaff2004Ssameeran joshiclass. 175eaff2004Ssameeran joshi1. Use move semantics and smart pointers to make dynamic memory ownership 176eaff2004Ssameeran joshiclear. Consider reworking any code that uses `malloc()` or a (non-placement) 177eaff2004Ssameeran joshi`operator new`. 178eaff2004Ssameeran joshiSee the section on Pointers below for some suggested options. 179eaff2004Ssameeran joshi1. When defining argument types, use values when object semantics are 180eaff2004Ssameeran joshinot required and the value is small and copyable without allocation 181eaff2004Ssameeran joshi(e.g., `int`); 182eaff2004Ssameeran joshiuse `const` or rvalue references for larger values (e.g., `std::string`); 183eaff2004Ssameeran joshiuse `const` references to rather than pointers to immutable objects; 184eaff2004Ssameeran joshiand use non-`const` references for mutable objects, including "output" arguments 185eaff2004Ssameeran joshiwhen they can't be function results. 186eaff2004Ssameeran joshiPut such output arguments last (_pace_ the standard C library conventions for `memcpy()` & al.). 187eaff2004Ssameeran joshi1. Prefer `typename` to `class` in template argument declarations. 188eaff2004Ssameeran joshi1. Prefer `enum class` to plain `enum` wherever `enum class` will work. 189eaff2004Ssameeran joshiWe have an `ENUM_CLASS` macro that helps capture the names of constants. 190eaff2004Ssameeran joshi1. Use `constexpr` and `const` generously. 191eaff2004Ssameeran joshi1. When a `switch()` statement's labels do not cover all possible case values 192eaff2004Ssameeran joshiexplicitly, it should contain either a `default:;` at its end or a 193eaff2004Ssameeran joshi`default:` label that obviously crashes; we have a `CRASH_NO_CASE` macro 194eaff2004Ssameeran joshifor such situations. 195eaff2004Ssameeran joshi1. On the other hand, when a `switch()` statement really does cover all of 196eaff2004Ssameeran joshithe values of an `enum class`, please insert a call to the `SWITCH_COVERS_ALL_CASES` 197eaff2004Ssameeran joshimacro at the top of the block. This macro does the right thing for G++ and 198eaff2004Ssameeran joshiclang to ensure that no warning is emitted when the cases are indeed all covered. 199eaff2004Ssameeran joshi1. When using `std::optional` values, avoid unprotected access to their content. 200eaff2004Ssameeran joshiThis is usually by means of `x.has_value()` guarding execution of `*x`. 201eaff2004Ssameeran joshiThis is implicit when they are function results assigned to local variables 202eaff2004Ssameeran joshiin `if`/`while` predicates. 203eaff2004Ssameeran joshiWhen no presence test is obviously protecting a `*x` reference to the 204eaff2004Ssameeran joshicontents, and it is assumed that the contents are present, validate that 205eaff2004Ssameeran joshiassumption by using `x.value()` instead. 206eaff2004Ssameeran joshi1. We use `c_str()` rather than `data()` when converting a `std::string` 207eaff2004Ssameeran joshito a `const char *` when the result is expected to be NUL-terminated. 208eaff2004Ssameeran joshi1. Avoid explicit comparisions of pointers to `nullptr` and tests of 209eaff2004Ssameeran joshipresence of `optional<>` values with `.has_value()` in the predicate 210eaff2004Ssameeran joshiexpressions of control flow statements, but prefer them to implicit 211eaff2004Ssameeran joshiconversions to `bool` when initializing `bool` variables and arguments, 212eaff2004Ssameeran joshiand to the use of the idiom `!!`. 213eaff2004Ssameeran joshi 214eaff2004Ssameeran joshi#### Classes 215eaff2004Ssameeran joshi1. Define POD structures with `struct`. 216eaff2004Ssameeran joshi1. Don't use `this->` in (non-static) member functions, unless forced to 217eaff2004Ssameeran joshido so in a template member function. 218eaff2004Ssameeran joshi1. Define accessor and mutator member functions (implicitly) inline in the 219eaff2004Ssameeran joshiclass, after constructors and assignments. Don't needlessly define 220eaff2004Ssameeran joshi(implicit) inline member functions in classes unless they really solve a 221eaff2004Ssameeran joshiperformance problem. 222eaff2004Ssameeran joshi1. Try to make class definitions in headers concise specifications of 223eaff2004Ssameeran joshiinterfaces, at least to the extent that C++ allows. 224eaff2004Ssameeran joshi1. When copy constructors and copy assignment are not necessary, 225eaff2004Ssameeran joshiand move constructors/assignment is present, don't declare them and they 226eaff2004Ssameeran joshiwill be implicitly deleted. When neither copy nor move constructors 227eaff2004Ssameeran joshior assignments should exist for a class, explicitly `=delete` all of them. 228eaff2004Ssameeran joshi1. Make single-argument constructors (other than copy and move constructors) 229eaff2004Ssameeran joshi'explicit' unless you really want to define an implicit conversion. 230eaff2004Ssameeran joshi 231eaff2004Ssameeran joshi#### Pointers 232eaff2004Ssameeran joshiThere are many -- perhaps too many -- means of indirect addressing 233eaff2004Ssameeran joshidata in this project. 234eaff2004Ssameeran joshiSome of these are standard C++ language and library features, 235eaff2004Ssameeran joshiwhile others are local inventions in `lib/Common`: 236eaff2004Ssameeran joshi* Bare pointers (`Foo *p`): these are obviously nullable, non-owning, 237eaff2004Ssameeran joshiundefined when uninitialized, shallowly copyable, reassignable, and often 238eaff2004Ssameeran joshinot the right abstraction to use in this project. 239eaff2004Ssameeran joshiBut they can be the right choice to represent an optional 240eaff2004Ssameeran joshinon-owning reference, as in a function result. 241eaff2004Ssameeran joshiUse the `DEREF()` macro to convert a pointer to a reference that isn't 242eaff2004Ssameeran joshialready protected by an explicit test for null. 243eaff2004Ssameeran joshi* References (`Foo &r`, `const Foo &r`): non-nullable, not owning, 244eaff2004Ssameeran joshishallowly copyable, and not reassignable. 245eaff2004Ssameeran joshiReferences are great for invisible indirection to objects whose lifetimes are 246eaff2004Ssameeran joshibroader than that of the reference. 247eaff2004Ssameeran joshiTake care when initializing a reference with another reference to ensure 248eaff2004Ssameeran joshithat a copy is not made because only one of the references is `const`; 249eaff2004Ssameeran joshithis is a pernicious C++ language pitfall! 250eaff2004Ssameeran joshi* Rvalue references (`Foo &&r`): These are non-nullable references 251eaff2004Ssameeran joshi*with* ownership, and they are ubiquitously used for formal arguments 252eaff2004Ssameeran joshiwherever appropriate. 253eaff2004Ssameeran joshi* `std::reference_wrapper<>`: non-nullable, not owning, shallowly 254eaff2004Ssameeran joshicopyable, and (unlike bare references) reassignable, so suitable for 255eaff2004Ssameeran joshiuse in STL containers and for data members in classes that need to be 256eaff2004Ssameeran joshicopyable or assignable. 257eaff2004Ssameeran joshi* `common::Reference<>`: like `std::reference_wrapper<>`, but also supports 258eaff2004Ssameeran joshimove semantics, member access, and comparison for equality; suitable for use in 259eaff2004Ssameeran joshi`std::variant<>`. 260eaff2004Ssameeran joshi* `std::unique_ptr<>`: A nullable pointer with ownership, null by default, 261eaff2004Ssameeran joshinot copyable, reassignable. 262eaff2004Ssameeran joshiF18 has a helpful `Deleter<>` class template that makes `unique_ptr<>` 263eaff2004Ssameeran joshieasier to use with forward-referenced data types. 264eaff2004Ssameeran joshi* `std::shared_ptr<>`: A nullable pointer with shared ownership via reference 265eaff2004Ssameeran joshicounting, null by default, shallowly copyable, reassignable, and slow. 266eaff2004Ssameeran joshi* `Indirection<>`: A non-nullable pointer with ownership and 267eaff2004Ssameeran joshioptional deep copy semantics; reassignable. 268eaff2004Ssameeran joshiOften better than a reference (due to ownership) or `std::unique_ptr<>` 269eaff2004Ssameeran joshi(due to non-nullability and copyability). 270eaff2004Ssameeran joshiCan be wrapped in `std::optional<>` when nullability is required. 271eaff2004Ssameeran joshiUsable with forward-referenced data types with some use of `extern template` 272eaff2004Ssameeran joshiin headers and explicit template instantiation in source files. 273eaff2004Ssameeran joshi* `CountedReference<>`: A nullable pointer with shared ownership via 274eaff2004Ssameeran joshireference counting, null by default, shallowly copyable, reassignable. 275eaff2004Ssameeran joshiSafe to use *only* when the data are private to just one 276eaff2004Ssameeran joshithread of execution. 277eaff2004Ssameeran joshiUsed sparingly in place of `std::shared_ptr<>` only when the overhead 278eaff2004Ssameeran joshiof that standard feature is prohibitive. 279eaff2004Ssameeran joshi 280eaff2004Ssameeran joshiA feature matrix: 281eaff2004Ssameeran joshi 282eaff2004Ssameeran joshi| indirection | nullable | default null | owning | reassignable | copyable | undefined type ok? | 283eaff2004Ssameeran joshi| ----------- | -------- | ------------ | ------ | ------------ | -------- | ------------------ | 284eaff2004Ssameeran joshi| `*p` | yes | no | no | yes | shallowly | yes | 285eaff2004Ssameeran joshi| `&r` | no | n/a | no | no | shallowly | yes | 286eaff2004Ssameeran joshi| `&&r` | no | n/a | yes | no | shallowly | yes | 287eaff2004Ssameeran joshi| `reference_wrapper<>` | no | n/a | no | yes | shallowly | yes | 288eaff2004Ssameeran joshi| `Reference<>` | no | n/a | no | yes | shallowly | yes | 289eaff2004Ssameeran joshi| `unique_ptr<>` | yes | yes | yes | yes | no | yes, with work | 290eaff2004Ssameeran joshi| `shared_ptr<>` | yes | yes | yes | yes | shallowly | no | 291eaff2004Ssameeran joshi| `Indirection<>` | no | n/a | yes | yes | optionally deeply | yes, with work | 292eaff2004Ssameeran joshi| `CountedReference<>` | yes | yes | yes | yes | shallowly | no | 293eaff2004Ssameeran joshi 294eaff2004Ssameeran joshi### Overall design preferences 295eaff2004Ssameeran joshiDon't use dynamic solutions to solve problems that can be solved at 296eaff2004Ssameeran joshibuild time; don't solve build time problems by writing programs that 297eaff2004Ssameeran joshiproduce source code when macros and templates suffice; don't write macros 298eaff2004Ssameeran joshiwhen templates suffice. Templates are statically typed, checked by the 299eaff2004Ssameeran joshicompiler, and are (or should be) visible to debuggers. 300eaff2004Ssameeran joshi 301eaff2004Ssameeran joshi### Exceptions to these guidelines 302eaff2004Ssameeran joshiReasonable exceptions will be allowed; these guidelines cannot anticipate 303eaff2004Ssameeran joshiall situations. 304eaff2004Ssameeran joshiFor example, names that come from other sources might be more clear if 305eaff2004Ssameeran joshitheir original spellings are preserved rather than mangled to conform 306eaff2004Ssameeran joshineedlessly to the conventions here, as Google's C++ style guide does 307eaff2004Ssameeran joshiin a way that leads to weirdly capitalized abbreviations in names 308eaff2004Ssameeran joshilike `Http`. 309eaff2004Ssameeran joshiConsistency is one of many aspects in the pursuit of clarity, 310eaff2004Ssameeran joshibut not an end in itself. 311eaff2004Ssameeran joshi 312eaff2004Ssameeran joshi## C++ compiler bug workarounds 313eaff2004Ssameeran joshiBelow is a list of workarounds for C++ compiler bugs met with f18 that, even 314eaff2004Ssameeran joshiif the bugs are fixed in latest C++ compiler versions, need to be applied so 315eaff2004Ssameeran joshithat all desired tool-chains can compile f18. 316eaff2004Ssameeran joshi 317eaff2004Ssameeran joshi### Explicitly move noncopyable local variable into optional results 318eaff2004Ssameeran joshi 319eaff2004Ssameeran joshiThe following code is legal C++ but fails to compile with the 320eaff2004Ssameeran joshidefault Ubuntu 18.04 g++ compiler (7.4.0-1ubuntu1~18.0.4.1): 321eaff2004Ssameeran joshi 322eaff2004Ssameeran joshi``` 323eaff2004Ssameeran joshiclass CantBeCopied { 324eaff2004Ssameeran joshi public: 325eaff2004Ssameeran joshi CantBeCopied(const CantBeCopied&) = delete; 326eaff2004Ssameeran joshi CantBeCopied(CantBeCopied&&) = default; 327eaff2004Ssameeran joshi CantBeCopied() {} 328eaff2004Ssameeran joshi}; 329eaff2004Ssameeran joshistd::optional<CantBeCopied> fooNOK() { 330eaff2004Ssameeran joshi CantBeCopied result; 331eaff2004Ssameeran joshi return result; // Legal C++, but does not compile with Ubuntu 18.04 default g++ 332eaff2004Ssameeran joshi} 333eaff2004Ssameeran joshistd::optional<CantBeCopied> fooOK() { 334eaff2004Ssameeran joshi CantBeCopied result; 335eaff2004Ssameeran joshi return {std::move(result)}; // Compiles OK everywhere 336eaff2004Ssameeran joshi} 337eaff2004Ssameeran joshi``` 338eaff2004Ssameeran joshiThe underlying bug is actually not specific to `std::optional` but this is the most common 339eaff2004Ssameeran joshicase in f18 where the issue may occur. The actual bug can be reproduced with any class `B` 340eaff2004Ssameeran joshithat has a perfect forwarding constructor taking `CantBeCopied` as argument: 341eaff2004Ssameeran joshi`template<typename CantBeCopied> B(CantBeCopied&& x) x_{std::forward<CantBeCopied>(x)} {}`. 342eaff2004Ssameeran joshiIn such scenarios, Ubuntu 18.04 g++ fails to instantiate the move constructor 343eaff2004Ssameeran joshiand to construct the returned value as it should, instead it complains about a 344eaff2004Ssameeran joshimissing copy constructor. 345eaff2004Ssameeran joshi 346eaff2004Ssameeran joshiLocal result variables do not need to and should not be explicitly moved into optionals 347eaff2004Ssameeran joshiif they have a copy constructor. 348