Update C++ style guide (#835)
- Explicitly ban `long double`
- Use absl formatting libraries or `std::ostream` over printf-style
functions.
- Portability: use serialization libraries instead of copying the
in-memory representation.
- Update guidance to use `uintptr_t` (previously `intptr_t`) when
working with pointers as integers.
- Ban C++20 modules.
- Ban coroutines (though this is expected to be temporary).
- Minor wording updates.
diff --git a/cppguide.html b/cppguide.html
index 7c87799..dca5dfe 100644
--- a/cppguide.html
+++ b/cppguide.html
@@ -3026,70 +3026,53 @@
representing bitfields or modular arithmetic). Do not use an unsigned
type merely to assert that a variable is non-negative.</p>
-<h3 id="64-bit_Portability">64-bit Portability</h3>
+<h3 id="Floating-Point_Types">Floating-Point Types</h3>
-<p>Code should be 64-bit and 32-bit friendly. Bear in mind
-problems of printing, comparisons, and structure alignment.</p>
+<p>Of the built-in C++ floating-point types, the only ones used
+ are <code>float</code> and
+<code>double</code>. You may assume that these types represent IEEE-754 binary32
+and binary64, respectively.</p>
+
+<p>Do not use <code>long double</code>, as it gives non-portable
+results.</p>
+
+<a id="64-bit_Portability"></a>
+<h3 id="Architecture_Portability">Architecture Portability</h3>
+
+<p>Write architecture-portable code. Do not rely on CPU features specific to a
+single processor.</p>
<ul>
- <li>
- <p>Correct portable <code>printf()</code> conversion specifiers for
- some integral typedefs rely on macro expansions that we find unpleasant to
- use and impractical to require (the <code>PRI</code> macros from
- <code><cinttypes></code>). Unless there is no reasonable alternative
- for your particular case, try to avoid or even upgrade APIs that rely on the
- <code>printf</code> family. Instead use a library supporting typesafe numeric
- formatting, such as
+ <li>When printing values, use type-safe numeric formatting libraries like
+ <a href="https://github.com/abseil/abseil-cpp/blob/master/absl/strings/str_cat.h"><code>absl::StrCat</code></a>,
+ <a href="https://github.com/abseil/abseil-cpp/blob/master/absl/strings/substitute.h"><code>absl::Substitute</code></a>,
+ <a href="https://github.com/abseil/abseil-cpp/blob/master/absl/strings/str_format.h"><code>absl::StrFormat</code></a>,
+ or <a href="#Streams"><code>std::ostream</code></a> instead of the
+ <code>printf</code> family of functions.</li>
-
- <a href="https://github.com/abseil/abseil-cpp/blob/master/absl/strings/str_cat.h"><code>StrCat</code></a>
-
- or
-
-
- <a href="https://github.com/abseil/abseil-cpp/blob/master/absl/strings/substitute.h"><code>Substitute</code></a>
-
- for fast simple conversions,
-
- or <a href="#Streams"><code>std::ostream</code></a>.</p>
-
- <p>Unfortunately, the <code>PRI</code> macros are the only portable way to
- specify a conversion for the standard bitwidth typedefs (e.g.,
- <code>int64_t</code>, <code>uint64_t</code>, <code>int32_t</code>,
- <code>uint32_t</code>, etc).
- Where possible, avoid passing arguments of types specified by bitwidth
- typedefs to <code>printf</code>-based APIs. Note that it is acceptable
- to use typedefs for which printf has dedicated length modifiers, such as
- <code>size_t</code> (<code>z</code>),
- <code>ptrdiff_t</code> (<code>t</code>), and
- <code>maxint_t</code> (<code>j</code>).</p>
+ <li>When moving structured data into or out of your process, encode it using a
+ serialization library like
+ <a href="https://protobuf.dev/">Protocol
+ Buffers</a> rather than copying the in-memory representation around.
</li>
- <li>Remember that <code>sizeof(void *)</code> !=
- <code>sizeof(int)</code>. Use <code>intptr_t</code> if
- you want a pointer-sized integer.</li>
-
- <li>You may need to be careful with structure
- alignments, particularly for structures being stored on
- disk. Any class/structure with a <code>int64_t</code>/<code>uint64_t</code>
- member will by default end up being 8-byte aligned on a
- 64-bit system. If you have such structures being shared
- on disk between 32-bit and 64-bit code, you will need
- to ensure that they are packed the same on both
- architectures.
- Most compilers offer a way to
- alter structure alignment. For gcc, you can use
- <code>__attribute__((packed))</code>. MSVC offers
- <code>#pragma pack()</code> and
- <code>__declspec(align())</code>.</li>
+ <li>If you need to work with memory addresses as integers, store them in
+ <code>uintptr_t</code>s rather than <code>uint32_t</code>s or
+ <code>uint64_t</code>s.</li>
<li>
- <p>Use <a href="#Casting">braced-initialization</a> as needed to create
- 64-bit constants. For example:</p>
+ Use <a href="#Casting">braced-initialization</a> as needed to create
+ 64-bit constants. For example:
<pre>int64_t my_value{0x123456789};
uint64_t my_mask{uint64_t{3} << 48};
</pre>
</li>
+
+ <li>Use portable <a href="#Floating-Point_Types">floating point types</a>;
+ avoid <code>long double</code>.</li>
+
+ <li>Use portable <a href="#Integer_Types">integer types</a>; avoid
+ <code>short</code>, <code>long</code>, and <code>long long</code>.</li>
</ul>
<h3 id="Preprocessor_Macros">Preprocessor Macros</h3>
@@ -3893,6 +3876,37 @@
be imposed via other mechanisms such as comments, assertions,
or tests.</p>
+<h3 id="modules">C++20 modules</h3>
+
+<p>Do not use C++20 Modules.</p>
+
+<p>C++20 introduces "modules", a new language feature designed as an
+alternative to textual inclusion of header files. It introduces three
+new keywords to support
+this: <code>module</code>, export,
+and <code>import</code>.
+
+</p><p>Modules are a big shift in how C++ is written and compiled, and we
+are still assessing how they may fit into Google's C++ ecosystem in
+the future. Furthermore, they are not currently well-supported by our
+build-systems, compilers, and other tooling, and need further
+exploration as to the best-practices when writing and using them.</p>
+
+
+
+<h3 id="coroutines">Coroutines</h3>
+
+<p>Do not use coroutines (yet).</p>
+
+<p>Do not include the <code><coroutine></code> header,
+or use the <code>co_await</code>, <code>co_yield</code>,
+or <code>co_return</code> keywords.</p>
+
+<p>NOTE: this ban is expected to be temporary, while further
+guidance is being developed.
+
+</p>
+
<h3 id="Boost">Boost</h3>
<p>Use only approved libraries from the Boost library
@@ -3997,11 +4011,11 @@
-<h3 id="Other_Features"><a id="C++11">Other C++ Features</a></h3>
+<h3 id="Disallowed_Stdlib">Disallowed standard library features</h3>
<p>As with <a href="#Boost">Boost</a>, some modern C++
-extensions encourage coding practices that hamper
+library functionality encourages coding practices that hamper
readability—for example by removing
checked redundancy (such as type names) that may be
helpful to readers, or by encouraging template
@@ -4010,8 +4024,7 @@
and conversion costs.</p>
<p class="decision"></p>
-<p>In addition to what's described in the rest of the style
-guide, the following C++ features may not be used:</p>
+<p>The following C++ standard library features may not be used:</p>
<ul>
@@ -4330,8 +4343,8 @@
<li><code>myusefulclass_test.cc // _unittest and _regtest are deprecated.</code></li>
</ul>
-<p>C++ files should end in <code>.cc</code> and header files should end in
-<code>.h</code>. Files that rely on being textually included at specific points
+<p>C++ files should have a <code>.cc</code> filename extension, and header files
+should have a <code>.h</code> extension. Files that rely on being textually included at specific points
should end in <code>.inc</code> (see also the section on
<a href="#Self_contained_Headers">self-contained headers</a>).</p>
@@ -5917,7 +5930,7 @@
<div>
-<h3 id="Existing_Non-conformant_Code">Existing Non-conformant Code</h3>
+<h3 id="Existing_Non-conformant_Code" class="no-toc">Existing Non-conformant Code</h3>
<p>You may diverge from the rules when dealing with code that
does not conform to this style guide.</p>