logo

C++ - Caveats

Last Updated: 2022-02-25

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, enums 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)