blob: b05832c5e8f85364d9688c314e934f3c8edf4d68 [file] [log] [blame]
Keir Mierle2c1e56b2019-11-15 16:32:11 -08001.. _chapter-embedded-cpp:
2
3.. default-domain:: cpp
4
5.. highlight:: sh
6
7==================
8Embedded C++ Guide
9==================
10
11This page contains recommendations for using C++ for embedded software. For
12Pigweed code, these should be considered as requirements. For external
13projects, these recommendations can serve as a resource for efficiently using
14C++ in embedded projects.
15
16These recommendations are subject to change as the C++ standard and compilers
17evolve, and as the authors continue to gain more knowledge and experience in
18this area. If you disagree with recommendations, please discuss them with the
19Pigweed team, as we're always looking to improve the guide or correct any
20inaccuracies.
21
22Constexpr functions
23===================
24Constexpr functions are functions that may be called from a constant
25expression, such as a template parameter, constexpr variable initialization, or
26``static_assert`` statement. Labeling a function ``constexpr`` does not
27guarantee that it is executed at compile time; if called from regular code, it
28will be compiled as a regular function and executed at run time.
29
30Constexpr functions are implicitly inline, which means they are suitable to be
31defined in header files. Like any function in a header, the compiler is more
32likely to inline it than other functions. Marking non-trivial functions as
33``constexpr`` could increase code size, so check the compilation results if this
34is a concern.
35
36Simple constructors should be marked ``constexpr`` whenever possible. GCC
37produces smaller code in some situations when the ``constexpr`` specifier is
38present. Do not avoid important initialization in order to make the class
39constexpr-constructible unless it actually needs to be used in a constant
40expression.
41
42Constexpr variables
43===================
44Constants should be marked ``constexpr`` whenever possible. Constexpr variables
45can be used in any constant expression, such as a non-type template argument,
46``static_assert`` statement, or another constexpr variable initialization.
47Constexpr variables can be initialized at compile time with values calculated by
48constexpr functions.
49
50``constexpr`` implies ``const`` for variables, so there is no need to include
51the ``const`` qualifier when declaring a constexpr variable.
52
53Unlike constexpr functions, constexpr variables are **not** implicitly inline.
54Constexpr variables in headers must be declared with the ``inline`` specifier.
55
56.. code-block:: cpp
57
58 namespace pw {
59
60 inline constexpr const char* kStringConstant = "O_o";
61
62 inline constexpr float kFloatConstant1 = CalculateFloatConstant(1);
63 inline constexpr float kFloatConstant2 = CalculateFloatConstant(2);
64
65 } // namespace pw
66
67Function templates
68==================
69Function templates facilitate writing code that works with different types. For
70example, the following clamps a value within a minimum and maximum:
71
72.. code-block:: cpp
73
74 template <typename T>
75 T Clamp(T min, T max, T value) {
76 if (value < min) {
77 return min;
78 }
79 if (value > max) {
80 return min;
81 }
82 return value;
83 }
84
85The above code works seamlessly with values of any type -- float, int, or even a
86custom type that supports the < and > operators.
87
88The compiler implements templates by generating a separate version of the
89function for each set of types it is instantiated with. This can increase code
90size significantly.
91
92.. tip::
93
94 Be careful when instantiating non-trivial template functions with multiple
95 types.
96
97Virtual functions
98=================
99Virtual functions provide for runtime polymorphism. Unless runtime polymorphism
100is required, virtual functions should be avoided. Virtual functions require a
101virtual table, which increases RAM usage and requires extra instructions at each
102call site. Virtual functions can also inhibit compiler optimizations, since the
103compiler may not be able to tell which functions will actually be invoked. This
104can prevent linker garbage collection, resulting in unused functions being
105linked into a binary.
106
107When runtime polymorphism is required, virtual functions should be considered.
108C alternatives, such as a struct of function pointers, could be used instead,
109but these approaches may offer no performance advantage while sacrificing
110flexibility and ease of use.
111
112.. tip::
113
114 Only use virtual functions when runtime polymorphism is needed.