summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2016-09-25 03:27:09 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2016-09-25 03:27:09 +0200
commitce22517f30193f79011f4345b365301a9e6183f5 (patch)
tree680d9a6cf8f4dadedb1f1708fd431fc54baab464
parent8424d71f135b7872fd2db40969758ed7e3c1071c (diff)
Start C++ style document
-rw-r--r--cxx-style.txt59
1 files changed, 59 insertions, 0 deletions
diff --git a/cxx-style.txt b/cxx-style.txt
new file mode 100644
index 0000000..64af573
--- /dev/null
+++ b/cxx-style.txt
@@ -0,0 +1,59 @@
+0. Don't try to be clever, prefer value/move semantics
+
+These days optimizers can often "see through" (via constexpr/inline/lto) and
+optimize simple code that uses value semantics to the equivalent (or even
+better) "clever" code that tries to avoid extra copies, allocations, etc.
+
+See also the note on small value optimization.
+
+1. Almost never auto
+
+Using auto instead of the actual type often makes code harder to understand.
+You may (but don't have to) use auto when (a) the type is spelled out on the
+right hand side (e.g., casts, make_*<>() functions, etc), and (b) in cases of
+idiomatic use where the type is clear to anyone familiar with C++ and it would
+be painful to spell it out explicitly.
+
+Examples of the latter are lambda initializations, iterator initializations
+(e.g, from begin()), and some cases of pair initialization (e.g, from
+container's insert()).
+
+2. Almost never brace-initialization
+
+We only use brace-initialization syntax when initializing an aggregate or a
+container. We can also use it for an aggregate-like initialization of an
+aggregate-like class.
+
+An aggregate-like class is class with public data members only and an
+aggregate-like initialization is an initialization that provides initializers
+for every such data member. For example:
+
+struct foo
+{
+ int x, y;
+
+ foo (int x, int y);
+ foo (int both);
+};
+
+foo x {0, 1}; // Ok.
+foo x {0}; // Bad.
+
+For default member variable initialization use assignment syntax, for example:
+
+struct foo
+{
+ int i = 123;
+ string s = string (123, 's');
+};
+
+3. Many performance-critical standard types are "small object optimized"
+
+For example, across all the implementations that we care, std::string can hold
+at least 15 characters without allocation. Similarly, std::function can hold a
+lambda with at least 2 pointers also without allocation.
+
+As a result, it is seldom makes sense to resort to elaborate optimizations
+such as string pooling. In fact, if we have a string pool that contains mostly
+short, SOO strings, then we will most likely hurt performance due to lack of
+locality.