{"id":1441,"date":"2020-08-04T23:13:35","date_gmt":"2020-08-05T06:13:35","guid":{"rendered":"http:\/\/209.126.2.187\/?page_id=1441"},"modified":"2020-08-14T09:35:42","modified_gmt":"2020-08-14T16:35:42","slug":"c-readabilities","status":"publish","type":"page","link":"https:\/\/nanzhou.cc\/index.php\/c-readabilities\/","title":{"rendered":"C++ Readabilities"},"content":{"rendered":"\n<p>In this page, I will introduce some best practice recommended by Google. We should write readable, efficient, and extendable codes. <\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Use EXPECT_THAT &amp; ElementsAre &amp; UnorderedElementsAre<\/h2>\n\n\n\n<p>It can be more flexible than <code>EXPECT_EQ<\/code>.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"cpp\" class=\"language-cpp\">EXPECT_THAT(Foo(), ElementsAre(1, Gt(0), _, 10));<\/code><\/pre>\n\n\n\n<p>If no order is required, consider <code>UnorderedElementsAre<\/code>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Test Suite Names and Test Names not Contain Underscore<\/h2>\n\n\n\n<p><a href=\"https:\/\/github.com\/google\/googletest\/blob\/master\/googletest\/docs\/faq.md#why-should-test-suite-names-and-test-names-not-contain-underscore\">https:\/\/github.com\/google\/googletest\/blob\/master\/googletest\/docs\/faq.md#why-should-test-suite-names-and-test-names-not-contain-underscore<\/a><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Prefer Range-Based Loops<\/h2>\n\n\n\n<p>If possible, use <code>for (const auto i&amp; : v)<\/code> rather than index-based loops for better performance (same reason as avoiding <code>vector&lt;T>&amp;<\/code> below). <\/p>\n\n\n\n<p><a href=\"https:\/\/github.com\/isocpp\/CppCoreGuidelines\/blob\/master\/CppCoreGuidelines.md#Res-for-range\">https:\/\/github.com\/isocpp\/CppCoreGuidelines\/blob\/master\/CppCoreGuidelines.md#Res-for-range<\/a><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Avoid <code>vector&lt;T>&amp;<\/code> or <code>string &amp;<\/code><\/h2>\n\n\n\n<p>When using a pointer (or reference) to a container, it usually contains two levels of pointer arithmetic. Consider using <code>absl::Span<\/code> or <code>absl::string_view<\/code> instead.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"cpp\" class=\"language-cpp\">void Foo(vector&lt;T> &amp;a) {\n  a[0] = 1; \/\/ actually it is a->data()[0] = 1\n}\n\n\/\/ method 1\nvoid Foo(absl::Span&lt;T> a) {\n  a[0] = 1; \/\/ data[0]=1, only one level of pointer arithmetic\n}\n\n\/\/ method 2\nvoid Foo(vector&lt;T> &amp;a) {\n  absl::Span&lt;T> b(a);\n  for (...) {\n    b[i] = 1;\n  }\n}<\/code><\/pre>\n\n\n\n<p>Two levels of pointer arithmetic makes it really hard for compilers to do analysis. When read or write data in loops, <code>absl::Span<\/code> becomes much faster because of vectorization.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Avoid\u00a0<code>[]<\/code>\u00a0parameters, prefer\u00a0<code>span<\/code><\/h2>\n\n\n\n<p>Use\u00a0<code>absl::Span<\/code>\u00a0instead for better readability and safety.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Avoid Calling\u00a0<code>new<\/code>\u00a0&amp;\u00a0<code>delete<\/code>\u00a0Explicitly<\/h2>\n\n\n\n<p>Suggest using\u00a0<code>make_unique<\/code>\u00a0instead. <\/p>\n\n\n\n<p><a href=\"https:\/\/github.com\/isocpp\/CppCoreGuidelines\/blob\/master\/CppCoreGuidelines.md#r11-avoid-calling-new-and-delete-explicitly\">https:\/\/github.com\/isocpp\/CppCoreGuidelines\/blob\/master\/CppCoreGuidelines.md#r11-avoid-calling-new-and-delete-explicitly<\/a><\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><code>StrCat<\/code><\/h2>\n\n\n\n<p>Avoid <code>foo + bar + baz<\/code>, use <code>absl::StrCat(foo, bar, baz)<\/code> instead. Since for chains of&nbsp;<code>n<\/code>&nbsp;string concatenations, in the worst case, it requires&nbsp;<code>O(n)<\/code>&nbsp;reallocations.<\/p>\n\n\n\n<p>&nbsp;<a href=\"https:\/\/abseil.io\/tips\/3\">https:\/\/abseil.io\/tips\/3<\/a><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Order of Includes<\/h2>\n\n\n\n<p>Separate headers by sections. Within each section the includes should be ordered alphabetically.  No UNIX directory aliases&nbsp;<code>.<\/code>&nbsp;(the current directory) or&nbsp;<code>..<\/code>&nbsp;(the parent directory) please. <\/p>\n\n\n\n<ol class=\"wp-block-list\"><li><code><var>dir2\/foo2<\/var>.h<\/code> (the declaration if applicable)<\/li><li>A blank line<\/li><li>C system headers (more precisely: headers in angle brackets with the&nbsp;<code>.h<\/code>&nbsp;extension), e.g.,&nbsp;<code>&lt;unistd.h&gt;<\/code>,&nbsp;<code>&lt;stdlib.h&gt;<\/code>.<\/li><li>A blank line<\/li><li>C++ standard library headers (without file extension), e.g.,&nbsp;<code>&lt;algorithm&gt;<\/code>,&nbsp;<code>&lt;cstddef&gt;<\/code>.<\/li><li>A blank line<\/li><li>Other libraries&#8217;&nbsp;<code>.h<\/code>&nbsp;files.<\/li><li>Your project&#8217;s&nbsp;<code>.h<\/code>&nbsp;files<\/li><\/ol>\n\n\n\n<p>As an example, in <code>foo\/server\/fooserver.cc<\/code><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"cpp\" class=\"language-cpp\">#include \"foo\/server\/fooserver.h\"\n\n#include &lt;sys\/types.h>\n#include &lt;unistd.h>\n\n#include &lt;string>\n#include &lt;vector>\n\n#include \"base\/basictypes.h\"\n#include \"base\/commandlineflags.h\"\n#include \"foo\/server\/bar.h\"<\/code><\/pre>\n\n\n\n<p><a href=\"https:\/\/google.github.io\/styleguide\/cppguide.html#Names_and_Order_of_Includes\">Google&#8217;s C++ Stype Guide#Names_and_Order_of_Includes<\/a><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Namespace<\/h2>\n\n\n\n<ol class=\"wp-block-list\"><li>Do not use <code>using-directive (using namespace foo;)<\/code> <\/li><li>With few exceptions,&nbsp;place code in a namespace (include <code>using-declarations, like using foo::bar;<\/code>).<\/li><li>Fully qualify <code>using-declarations<\/code> and namespace aliases; in other cases, please try to avoid fully qualifying&nbsp;unless you must to make it compile;<\/li><li>Don&#8217;t introduce sub-namespaces with common names like&nbsp;<code>std<\/code>,&nbsp;<code>util<\/code>, or&nbsp;<code>testing<\/code>.<\/li><\/ol>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"cpp\" class=\"language-cpp\">namespace foo {\nusing ::foo1::bar::Baz;\nnamespace baz = ::foo2::bar::baz;\n}<\/code><\/pre>\n\n\n\n<p><a href=\"https:\/\/abseil.io\/tips\/153\">https:\/\/abseil.io\/tips\/153<\/a>, <a href=\"https:\/\/abseil.io\/tips\/130\">https:\/\/abseil.io\/tips\/130<\/a><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Namespace Lookup<\/h2>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"cpp\" class=\"language-cpp\">namespace foo {\nnamespace bar {\n\nvoid Func() {\n  Baz::HaHa b;\n}\n\n}  \/\/ namespace bar\n}  \/\/ namespace foo\n<\/code><\/pre>\n\n\n\n<p>In C++, lookup on an unqualified name (<code>Baz::HaHa<\/code>) will search expanding scopes for a symbol of the same name: first in&nbsp;<code>Func<\/code>&nbsp;(the function), then in&nbsp;<code>bar<\/code>, then in&nbsp;<code>foo<\/code>, then in the global namespace. <\/p>\n\n\n\n<p>If <code>Baz<\/code> refers to a global namespace and in <code>bar<\/code> there is another namespace called <code>Baz<\/code>, but without <code>HaHa<\/code> defined, then building will fail, since namespace lookup looked into <code>::foo::bar::Baz<\/code> first, failed, and stopped. Use fully qualified <code>::Baz::HaHa<\/code> will solve the problem.<\/p>\n\n\n\n<p><a href=\"https:\/\/abseil.io\/tips\/130\">https:\/\/abseil.io\/tips\/130<\/a><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Reduce Double-Negatives<\/h2>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"cpp\" class=\"language-cpp\">\/\/ bad\nif (!disable_b) {\n  DoA();\n} else {\n  DoB();\n}\n\n\/\/ good\nif (enable_b) {\n  DoB();\n} else {\n  DoA();\n}<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Reduce Nesting Levels<\/h2>\n\n\n\n<p>Level Depth is better to be no more than 2, which could be achieved by early return or separate functions.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"Function_Comments\">Function Comments<\/h2>\n\n\n\n<p>Declaration comments describe use of the function (comments&nbsp;should use the indicative mood&nbsp;like &#8220;Returns the area&#8221;, rather than the imperative &#8220;Return the area&#8221;; definition comments describe implementation details.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><code>string_view<\/code><\/h2>\n\n\n\n<p>Prefer <code>string_view<\/code>&nbsp;over&nbsp;<code>const char*<\/code> or <code>const string&amp;<\/code> as function parameters. <\/p>\n\n\n\n<p>Note that<code>string_view<\/code>&nbsp;is not necessarily NUL-terminated.<\/p>\n\n\n\n<p><a href=\"https:\/\/abseil.io\/tips\/1\">https:\/\/abseil.io\/tips\/1<\/a><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Avoid Boolean Parameters<\/h2>\n\n\n\n<p>Prefer enum over boolean parameters. <code>Foo(Feature::kA)<\/code> makes more sense than <code>Foo(\/*enable_A*\/true)<\/code>.<\/p>\n\n\n\n<p><a href=\"https:\/\/abseil.io\/tips\/94\">https:\/\/abseil.io\/tips\/94<\/a><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Output Parameters<\/h2>\n\n\n\n<p>Prefer return value over output parameters (please refer to <a href=\"https:\/\/github.com\/protocolbuffers\/protobuf\/blob\/master\/src\/google\/protobuf\/stubs\/statusor.h\">StatusOr<\/a> in protobuf, the <code>StatusOr<\/code> on Abseil is not open sourced yet). <\/p>\n\n\n\n<p>Also output parameters should be after input parameters.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Prefer <code>span<\/code> as Function Parameters<\/h2>\n\n\n\n<p>Same as string_view over&nbsp;<code>const char*<\/code> or <code>const string&amp;<\/code>, prefer <code>span&lt;const T&gt;<\/code> over <code>const T*<\/code> or <code>const vector&lt;T&gt;&amp;<\/code> as function parameters. <\/p>\n\n\n\n<p>Usually pass <code>span<\/code> or <code>string_view<\/code> by value, since it is not always faster to pass a pointer. See Copy Elision and Pass-by-value in <a href=\"https:\/\/abseil.io\/tips\/117\">https:\/\/abseil.io\/tips\/117<\/a>.<\/p>\n\n\n\n<p><a href=\"https:\/\/abseil.io\/tips\/93\">https:\/\/abseil.io\/tips\/93<\/a><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Qualifying <code>auto<\/code> <\/h2>\n\n\n\n<ol class=\"wp-block-list\"><li>Use <code>const auto&amp;<\/code> or <code>auto&amp;<\/code> unless a copy is needed;<\/li><li>Use  <code>const auto&amp;<\/code> unless you need to modify data;<\/li><li>Use <code>const auto*<\/code> or <code>auto*<\/code> to make pointer explicit;<\/li><\/ol>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"cpp\" class=\"language-cpp\">char num = 'a';\nchar* p1 = &num;\nauto p2 = p1;   \/\/ p2 is 'char*'\nauto* p3 = p1;  \/\/ p3 is 'char*' (same as bare auto)<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Reserve Size in Advance<\/h2>\n\n\n\n<p>Call reserve if the final size is known to avoid repeated allocation and the corresponding copy\/moves. <\/p>\n\n\n\n<p>Since if a reallocation happens, old values might be copied into the new memory.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Prefer <code>push_back<\/code> over <code>emplace_back<\/code><\/h2>\n\n\n\n<p>Prefer <code>push_back<\/code> over <code>emplace_back<\/code> unless the performance matters. Since <code>emplace_back<\/code> is too powerful. <\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"cpp\" class=\"language-cpp\">std::vector&lt;vector&lt;int>> vec;\nvec.push_back(1&lt;&lt;20); \/\/ compile error\nvec.emplace_back(1&lt;&lt;20); \/\/ no errors until run-time<\/code><\/pre>\n\n\n\n<p><a href=\"https:\/\/abseil.io\/tips\/112\">https:\/\/abseil.io\/tips\/112<\/a>, <a href=\"https:\/\/abseil.io\/tips\/65\">https:\/\/abseil.io\/tips\/65<\/a><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Global Constants<\/h2>\n\n\n\n<p>It is very common that people want to define static const variables in the global namespace. <\/p>\n\n\n\n<ol class=\"wp-block-list\"><li>One global variable shouldn&#8217;t rely on another global in a different translation unit (roughly, a <code>cc<\/code> file), since the order of initialization between translation units is unspecified.<\/li><li>Ensure the One Definition Rule (external linkage rather than internal linkage). This is important when address matters.<\/li><li>Global constants should be <a href=\"http:\/\/en.cppreference.com\/w\/cpp\/types\/is_destructible\">trivially destructible<\/a> (string is not). As a rule of thumb: a global variable satisfies these requirements if its declaration, considered in isolation, could be&nbsp;<code>constexpr<\/code>. <\/li><\/ol>\n\n\n\n<h4 class=\"wp-block-heading\">Constants in Header<\/h4>\n\n\n\n<p>Before C++17, use extern const variables.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"cpp\" class=\"language-cpp\">\/\/ constants.h\n#ifndef CONSTANTS_H\n#define CONSTANTS_H\n \nnamespace constants\n{\n    \/\/ since the actual variables are inside a namespace, the forward declarations need to be inside a namespace as well\n    extern const double pi;\n    extern const double avogadro;\n    extern const double my_gravity;\n}\n \n#endif\n\n\/\/ constants.cc\n#include \"constants.h\"\n \nnamespace constants\n{\n    \/\/ actual global variables\n    extern const double pi { 3.14159 };\n    extern const double avogadro { 6.0221413e23 };\n    extern const double my_gravity { 9.2 }; \/\/ m\/s^2 -- gravity is light on this planet\n}<\/code><\/pre>\n\n\n\n<p>After C++17, use inline variables.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"cpp\" class=\"language-cpp\">#ifndef CONSTANTS_H\n#define CONSTANTS_H\n \n\/\/ define your own namespace to hold constants\nnamespace constants\n{\n    inline constexpr double pi { 3.14159 }; \/\/ note: now inline constexpr\n    inline constexpr double avogadro { 6.0221413e23 };\n    inline constexpr double my_gravity { 9.2 }; \/\/ m\/s^2 -- gravity is light on this planet\n    \/\/ ... other related constants\n}\n#endif<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">Constants in Source<\/h4>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"cpp\" class=\"language-cpp\">constexpr int kNum = 42;\nconstexpr char kStr[] = \"hello\";\nconstexpr std::string_view kAnotherStr = \"world\";<\/code><\/pre>\n\n\n\n<p><a href=\"https:\/\/www.learncpp.com\/cpp-tutorial\/global-constants-and-inline-variables\/\">https:\/\/www.learncpp.com\/cpp-tutorial\/global-constants-and-inline-variables\/<\/a><\/p>\n\n\n\n<p><a href=\"https:\/\/google.github.io\/styleguide\/cppguide.html#Static_and_Global_Variables\">https:\/\/google.github.io\/styleguide\/cppguide.html#Static_and_Global_Variables<\/a><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Pass Primitives &amp; Enums by Value<\/h2>\n\n\n\n<p>Pass primitives and enumerators (including <code>enum class<\/code>) by value, since usually primitives are smaller than pointers. Passing by pointers or references also makes codes harder to be optimized by compiler. <\/p>\n","protected":false},"excerpt":{"rendered":"<p>In this page, I will introduce some best practice recommended by Google. We should write readable, efficient, and extendable codes. Use EXPECT_THAT &amp; ElementsAre &amp; UnorderedElementsAre It can be more flexible than EXPECT_EQ. If no order is required, consider UnorderedElementsAre. Test Suite Names and Test Names not Contain Underscore https:\/\/github.com\/google\/googletest\/blob\/master\/googletest\/docs\/faq.md#why-should-test-suite-names-and-test-names-not-contain-underscore Prefer Range-Based Loops If possible,&#8230;<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"footnotes":""},"class_list":["post-1441","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/nanzhou.cc\/index.php\/wp-json\/wp\/v2\/pages\/1441","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/nanzhou.cc\/index.php\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/nanzhou.cc\/index.php\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/nanzhou.cc\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/nanzhou.cc\/index.php\/wp-json\/wp\/v2\/comments?post=1441"}],"version-history":[{"count":47,"href":"https:\/\/nanzhou.cc\/index.php\/wp-json\/wp\/v2\/pages\/1441\/revisions"}],"predecessor-version":[{"id":1496,"href":"https:\/\/nanzhou.cc\/index.php\/wp-json\/wp\/v2\/pages\/1441\/revisions\/1496"}],"wp:attachment":[{"href":"https:\/\/nanzhou.cc\/index.php\/wp-json\/wp\/v2\/media?parent=1441"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}