cesium-native 0.43.0
|
This is a guide to writing C++ code for cesium-native. These guidelines are intended to help us write better C++ code by:
In all cases these are guidelines. There are sometimes good reasons to violate the advice given here. In particular, when writing code that is meant to integrate into another system, it is rarely a good idea to fight that other system's conventions.
cesium-native uses ISO Standard C++20.
We follow the C++ Core Guidelines, with a few exceptions. We suggest proceeding as follows:
A change to C++ Core Guidelines NL.17.
Use clang-format
and the .clang-format
configuration in the root of this repo. Easy. If you're using Visual Studio Code with the C/C++ extension installed, just run the "Format Document" command.
To format the source code from the command line, install node.js from https://nodejs.org/, and run npm install
in the project root directory. Then, in order to apply the formatting, run npm run format
.
We believe that source code should be readable and even beautiful, but that automated formatting is more important than either concern. Especially when readability is largely a matter of what we're used to, and beauty is mostly subjective. For our JavaScript / TypeScript code, we format our code with the ubiquitous Prettier tool. In C++, clang-format is widely used but there's no de facto style, and so we've created a clang-format style that tracks as close to Prettier as possible.
A change to C++ Core Guidelines NL.10.
Our naming differs from the naming proposed in the C++ Core Guidelines, primarily for consistency with our JavaScript and TypeScript code bases, but also because we don't like typing underscores as much as Bjarne does. Our conventions are:
PascalCase
.lowerCamelCase
.SCREAMING_SNAKE_CASE
.generateTextureCoordinates
or getParent
, or named for the question they answer, like contains
.Tileset
, parent
or boundingVolume
.C
.I
.p
, e.g. pThing
. This is justified because it's not meant to convey type information (not so useful), but rather as an easily-understood abbreviation for the descriptive name of what the variable actually is (very useful). The variable isn't a thing
, it's a pointer to a thing, but pointerToThing
would get annoying quickly. (see NL.5)maybe
.expected
._
, as in _boundingVolume
.A change to C++ Core Guidelines SF.8.
Use #pragma once
at the top of header files rather than manual inclusion guards. Even though #pragma once
is not technically ISO Standard C++, it is supported everywhere and manual inclusion guards are really tedious. If platform-specific differences in #pragma once
behavior are changing the meaning of our program, we may need to reconsider some other life choices (like dodgy use of symlinks), but our choice to use #pragma once
likely remains sound.
Not covered by C++ Core Guidelines.
#include
when you must.#include
a fwd.h type of file if one is provided. #include
the full implementation only when you must.A change to C++ Core Guidelines I.10 and NR.3.
cesium-native may be used in environments with exceptions disabled, such as in Web Assembly builds. Thus, we should not rely on exceptions for correct behavior. Some guidelines:
CESIUM_ASSERT
rather than by throwing exceptions. In CesiumJS, these kinds of checks would throw DeveloperError
and would be removed from release builds. CESIUM_ASSERT
is a more elegant way to do much the same. The C++ Core Guidelines (I.6 and I.8) suggest using the Expects
and Ensures
macros from the Guidelines Support Library instead, but we suggest sticking with CESIUM_ASSERT
for the time being.noexcept
.Not covered by C++ Core Guidelines.
cesium-native may be used in environments with RTTI disabled. Thus, use of RTTI, including dynamic_cast
, is disallowed.
A change to C++ Core Guidelines Con.1 and Con.4.
In general we follow the advice suggested in https://quuxplusone.github.io/blog/2022/01/23/dont-const-all-the-things/:
const
(Con.2).const
(Con.3).const
for local variables.const
for by-value parameters.const
for return types.const
for data members (C.12).A change to C++ Core Guidelines ES.11.
Avoid using auto
except in the following cases where writing the full type is burdensome or impossible:
Not covered by the C++ Core Guidelines.
->
and *
instead of value()
to access the contained value.has_value()
.Partly covered by C++ Core Guidelines.
int32_t
instead of int
.static_cast
.Not covered by C++ Core Guidelines.
Not covered by C++ Core Guidelines.
We use UTF-8 everywhere, including on Windows where UTF-16 is the more common approach to unicode. This philosophy and the practicalities of adopting it are very well described by UTF-8 Everywhere. In short:
std::string
and char*
everywhere. Mostly forget that std::wstring
and wchar_t
exist; you don't need them.std::string::size
and strlen
return the number of UTF-8 code units, which is the same as the number of bytes.fstream
API family on Windows. Make sure you read and understand How to do text on Windows.Not covered by C++ Core Guidelines.
Test
, e.g. TestModel
instead of ModelTests
.Not covered by C++ Core Guidelines.
this->
when accessing member variables and functions. This helps distinguish member variables from local variables and member functions from anonymous namespace functions./*static*/
.[[maybe_unused]]
when you can't comment out parameter names, such as when parameters are conditionally accessed by constexpr
logic.[i]
instead of .at(i)
for sequence containers like std::vector
and std::array
.