C++ - Caveats
C++ is very complicated, and not every feature is designed perfectly.
Avoid built-in integer types other than int
Why
- For historical reasons C / C++ does not precisely specify the sizes of integer types.
Alternatives
Use fixed types like int64_t
instead of the built-in types like short
, long
, long long
. Except that you can use int
in loops or other cases when it will never be too big.
(Note that short
, int
, long
are keywords, while std::int64_t
is part of the header cstdint
)
https://google.github.io/styleguide/cppguide.html#Integer_Types
Avoid Macros
Why
- Macros mean that the code you see is not the same as the code the compiler sees.
- Macros are global
Alternatives
Prefer inline
functions, enum
s and const
variables. Except for the #define
guards to prevent double inclusion of header files.
https://google.github.io/styleguide/cppguide.html#Preprocessor_Macros
Avoid std::bind
Why
std::bind()
doesn't just bind the first N arguments, you must instead specify every argument.- The compiler usually tells you if the caller is passing more arguments than you expect, but not for
std::bind()
Alternatives
bind_front()
supports partial function application.
- Use C++20
std::bind_front()
- Use Abseil:
absl::bind_front()
Read more: https://abseil.io/tips/108
Limitations of std::function
Why
std::function
is copyable by design, which means it has the same requirement of copyability for callables that are being stored in it, even if the std::function
is never copied, i.e. it will not compile if it contains a std::unique_ptr
: std::function<void()> f = [p = std::make_unique<int>(5)] {...};
Alternatives
C++23 introduces std::move_only_function
, it satisfies the requirements of MoveConstructible and MoveAssignable, but does not satisfy CopyConstructible or CopyAssignable.
Avoid Forward Declaration
https://google.github.io/styleguide/cppguide.html#Forward_Declarations
Alternatives
Include the headers you need.
Exceptions
Google style guide bans the use of exception (but it may not apply to your use case.)
Not just Google, it is also discussed in P2544R0 C++ exceptions are becoming more and more problematic
Avoid using run-time type information (RTTI)
RTTI = query the class of an object at run-time using typeid
or dynamic_cast
.
https://google.github.io/styleguide/cppguide.html#Run-Time_Type_Information__RTTI_
Avoid C cast
https://google.github.io/styleguide/cppguide.html#Casting
Alternatives
- Use
static_cast
, e.g.static_cast<float>(double_value)
- Use brace initialization for conversion of arithmetic types like
int64_t y = int64_t{1} << 42
Avoid const_cast
(TODO)