C++ Style Comparison: Google Style Guide vs CppCore Guidelines #657
AlexanderLanin
started this conversation in
Operational Community
Replies: 0 comments
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
Intro
We'll follow MISRA, that's not the question here. The core guidelines is an alternative to MISRA (no judgement here), however that's not the point of this comparison. Here I want to focus on "style" only. Whatever "style" means.
I'll attempt to map the guidelines and highlight the differences.
No idea whether that will work out or not.
References
Mapping
We'll use the categories from the Google Style Guide, as they provide a clearer structure.
Caution
The following is provided by ChatGPT. ChatGPT can make mistakes. Check important info.
#define
Guard (header include guards)#include
guards for all .h files” (SF: Source files – C++). Also advises making guard unique (e.g. include project/component in macro) (SF: Source files – C++).PROJECT_PATH_FILE_H_
).""
for project headers and<>
for others (SF.12 (SF: Source files – C++)) and to include headers before other declarations (SF: Source files – C++). No fixed global->local order rule, but consistency is advised.using namespace
at global scope in headers (SF.7 (SF: Source files – C++)). All code should be in namespaces (exceptmain
or special cases).using namespace
(e.g., MISRA C++ 2008 Rule 7-3-4 forbids unnamed namespaces in headers and Rule 7-3-5 forbids using-directives in headers (Guidelines for the use of the C++14 language in critical and safety-related systems)). Code is expected to be organized into namespaces (to avoid name collisions).using namespace
at global scope. (Unnamed namespaces for internal linkage are allowed in .cpp, but not in headers.)static
or unnamed namespace is recommended for internal linkage.static
or unnamed namespace) in implementation files, to avoid polluting global namespace and prevent ODR violations.thread_local
. They implicitly allowthread_local
usage. Best practice in core/C++ is thatthread_local
objects follow the same rules as other static-duration objects regarding initialization (const-initialized if possible). Core would expectthread_local
to be used judiciously (e.g., for POD types or with constant initialization to avoid surprises).thread_local
(which is a C++11 feature). AUTOSAR emphasizes that any static-duration object (includingthread_local
) should have deterministic initialization. There is an expectation (not a formal rule) to initializethread_local
variables with constant expressions to avoid dynamic initialization issues at runtime, in line with Google’s rule.thread_local
init – Google requiresthread_local
variables to be initialized with a compile-time constant (prevent dynamic init) (Google C++ Style Guide). Core/AUTOSAR do not explicitly call this out, but implicitly prefer static-duration objects (including thread_local) to have constant initialization for safety. No direct conflict – more of a Google-specific emphasis.explicit
)explicit
” (C: Classes and class hierarchies – C++) (C: Classes and class hierarchies – C++). Core also requires conversion operators to be marked explicit (in C++11 and above) unless truly intended to be implicit. This matches Google’s rule to not allow implicit conversions.explicit
(Guidelines for the use of the C++14 language in critical and safety-related systems). In practice, AUTOSAR insists onexplicit
for single-parameter ctors to prevent unintended conversions.explicit
– All enforce using theexplicit
keyword for single-argument constructors and conversion operators to avoid unintended implicit conversions (Google C++ Style Guide) (C: Classes and class hierarchies – C++). (Copy/move constructors are exceptions and remain non-explicit.)struct
for passive data objects)struct
vsclass
. They note thatstruct
andclass
differ only by default access. However, the intent (as per C++ community practice) is similar to Google’s: usestruct
for simple data aggregates with public data and no invariants, and useclass
for types with invariants or complex behavior. (This isn’t an explicit Core rule, but it’s a common guideline consistent with Google’s.)struct
orclass
based on content. It treats them interchangeably except for access control. Typically, AUTOSAR code will useclass
for most user-defined types (with appropriate access specifiers), but this is not a strict rule. There is no prohibition on usingstruct
for POD types; it’s left to project style.struct
vsclass
– Google explicitly says to usestruct
only for plain data holders (all-public, no invariants) (Google C++ Style Guide) (Google C++ Style Guide). Core/AUTOSAR do not have a formal rule, but generally agree in spirit: if an object has no invariants and is just data,struct
is acceptable. (It’s a matter of style; not enforced outside Google.)std::pair
/std::tuple
)std::pair
orstd::tuple
. (In the community, it’s advised to usepair/tuple
only for very short-lived or obvious cases; otherwise define a struct.) So core’s philosophy aligns, though no explicit rule text.std::pair
orstd::tuple
. (AUTOSAR does allowstd::pair
andstd::tuple
since they are part of C++14, but expects judicious use.)std::pair
orstd::tuple
for readability (Google C++ Style Guide). Core and AUTOSAR have no formal rule, but generally value clarity – using a struct with descriptive member names is usually recommended for maintainability (especially in long-lived or widely used interfaces).override
. These match Google’s points (only use public inheritance for true is-a, minimize multiple/base classes).final
appropriately; core has similar guidance with theoverride
specifier.)because you can’t replicate short-circuit or sequencing semantics). **C.162**–**C.168** cover overloading conventions (e.g., if you overload
==, also overload
!=, etc.). They align with Google’s note to overload operators judiciously and only in intuitive ways ([Google C++ Style Guide](https://google.github.io/styleguide/cppguide.html#:~:text=Operator%20Overloading)) ([Google C++ Style Guide](https://google.github.io/styleguide/cppguide.html#:~:text=,may%20require%20a%20search%20tool)). Core also discourages user-defined literals in most cases (no specific rule, but they are rarely used in the standard library except for suffixes like
_s` etc.).string
andconst char*
is fine, but if semantics differ, use different function names. (This is in line with Google’s rule, though core doesn’t have a single rule number for it – it’s general advice.)auto func() -> Type
)decltype
. For typical functions, AUTOSAR code usually uses the conventional return type syntax, aligning with Google’s advice to prefer the ordinary syntax unless trailing form is clearer.-> Type
syntax should be used only when it improves readability (e.g., in complex template situations or for lambda declarations) (Google C++ Style Guide). No guideline forbids it – it’s a matter of clarity. Google explicitly advises against overusing trailing returns, which is consistent with general practice.const T&
or value, and using pointers or references only for in-out parameters, which mirrors Google’s rules for parameter passing (inputs by value or const-ref, outputs as pointer or returned) (Google C++ Style Guide) (Google C++ Style Guide).const&
(and usestd::optional
if an input is optional), outputs should ideally be returned or, if multiple outputs, passed as pointers (which can be null to signify “unused”) (Google C++ Style Guide). This makes it clear at call sites what is an out-param. Google’s specific guidance on using pointers for optional outputs is consistent with AUTOSAR practices.noexcept
(use of noexcept specifier)noexcept
for functions that are not supposed to throw. For example, move constructors/assignments should benoexcept
(C.66). They caution thatnoexcept
should reflect true no-throw guarantees. This aligns with Google’s advice to mark functionsnoexcept
when they won’t/can’t throw (especially important in exception-enabled code for optimization) (Google C++ Style Guide) (Google C++ Style Guide).noexcept
for functions that are guaranteed not to throw (since AUTOSAR allows exceptions,noexcept
helps optimizations and clarity). There’s an AUTOSAR rule (A15-3-3) that destructors should be noexcept by default, and recommendations to declare move constructorsnoexcept
. No conflict here with Google, which also suggests noexcept where applicable (even though Google’s code typically doesn’t throw, they use noexcept for things like move ops).noexcept
usage – All agree on usingnoexcept
for functions that are meant not to throw (particularly special member functions like moves) (Google C++ Style Guide). Google notes it’s hard to guarantee in exception-disabled builds, but still encourages marking functions noexcept for clarity/performance. Core and AUTOSAR, working with exceptions, explicitly usenoexcept
to enable optimizations (e.g., in containers) and to denote non-throwing functions.dynamic_cast
,typeid
)dynamic_cast
/typeid
have legitimate uses (when type-safe downcast is needed), but suggest alternatives like visitor pattern or virtual functions first. This is less strict than Google’s “avoid RTTI” stance (Google C++ Style Guide) (Google C++ Style Guide).dynamic_cast
in safety critical code. The AUTOSAR guidelines say RTTI “is prone to abuse” and should be avoided. It permits it only in test or very controlled scenarios. This is very close to Google’s rule to avoid RTTI (Google C++ Style Guide) (Google C++ Style Guide). (If RTTI-like behavior is needed, AUTOSAR would prefer alternative designs as well.)dynamic_cast
when necessary (they consider it a tool for specific cases). AUTOSAR is closer to Google here: RTTI is essentially forbidden in high-integrity code. Summary: Google/AUTOSAR disallow or strongly discourage RTTI; Core allows it with caution.static_cast
,const_cast
,reinterpret_cast
as appropriate, and prefer avoiding casts overall if possible. This matches Google’s rule to use C++-style casts (and brace-initialization for numeric conversions) (Google C++ Style Guide) (Google C++ Style Guide). Core also mentions usinggsl::narrow
or similar for narrowing conversions (Google uses brace-init to catch narrowing).static_cast
/dynamic_cast
/reinterpret_cast
/const_cast
instead of C casts. AUTOSAR additionally states that casting away const or downcasting should be done carefully (or not at all). Google’s recommendations (use C++ casts and only when necessary) line up exactly.static_cast
/const_cast
etc. for explicit conversions (Google C++ Style Guide) (Google C++ Style Guide). They also agree on using brace initialization for safe numeric conversions (Google explicitly says so (Google C++ Style Guide), Core/AUTOSAR concur in principle on avoiding unchecked narrowing). Overall, casting is to be done in a controlled, explicit manner in all standards.<<
with non-standard semantics, and don’t expose internal state in operator<< – these align with general best practice rather than explicit Core rules.) Core’s focus is more on not usingprintf
in modern C++ when streams suffice, which is implicitly aligned with Google.<iostream>
, but in practice, heavy use of iostreams in embedded/safety code is rare (due to performance and determinism concerns). AUTOSAR guidelines don’t forbid it for debugging or logging. Google’s advice to keep streaming simple (only user-visible content, no complex hidden side effects) is generally good practice and would be expected in AUTOSAR code if streams are used.<iostream>
for logging/debug output and simple formatting, and cautions to keep overloaded<<
operators straightforward (only output user-visible state) (Google C++ Style Guide) (Google C++ Style Guide). Core/AUTOSAR have no contrary rules – they accept iostreams as standard. (AUTOSAR developers may limit iostream use for performance, but that’s contextual.) All agree that if you do overload output operators, do so in an unsurprising, simple way.constexpr
,inline
, templates, etc. instead of#define
. If macros are needed, they suggest naming them ALL_CAPS (and possibly with a project-specific prefix to avoid collisions) (SF: Source files – C++). This is fully in line with Google’s rule (which also requires a project prefix on macro names and discourages macro APIs) (Google C++ Style Guide) (Google C++ Style Guide).inline
orconst
instead) (Guidelines for the use of the C++14 language in critical and safety-related systems). This completely aligns with Google: macros are last resort (and must be all-caps with meaningful prefixes when used).auto
only when it aids clarity)auto
to avoid repetition, but with judgement. They state to useauto
when the type is obvious from context or unimportant to the reader (Improving Stability with Modern C++, Part 3 — The auto Keyword). This is similar to Google’s rule of using type deduction only if it makes code clearer or safer, not just to save typing (Google C++ Style Guide) (Google C++ Style Guide). Core might endorseauto
slightly more (to avoid long type names), but they also warn against cases where it hinders understanding. Overall, the philosophy is the same; the emphasis differs slightly.auto
. It can be used (C++14). The AUTOSAR/MISRA view is thatauto
is fine if it does not impair code clarity. Tools in safety-critical projects might flag overuse ofauto
if it obscures types. In practice, AUTOSAR code usesauto
in obvious situations (iterators, lambdas) but not in cases where the type’s meaning isn’t clear. This practically aligns with Google’s guidance.auto
deduction – All agree thatauto
should be used with caution. Use it when it makes code cleaner (eliminating noise or obvious redundancy) (Google C++ Style Guide), but not when it would make the code less readable to someone unfamiliar. Google explicitly says not to useauto
just to avoid typing a type name (Google C++ Style Guide). Core/AUTOSAR share that intent – they allowauto
, but expect developers to maintain clarity.std::make_unique
was preferred pre-C++17, but CTAD for smart pointers isn’t available. Core hasn’t flagged CTAD as problematic.) Thus, Core is more permissive whereas Google says only use CTAD when the template author explicitly intended it (to avoid surprises).make_unique
or providing explicit template args. Google’s rule effectively prohibits CTAD unless guaranteed safe – but AUTOSAR outright cannot use it until they update to C++17 or later (not within AUTOSAR C++14 guidelines).mutable
only if needed, and not to copy mutable data inadvertently – generally consistent with Google’s best practices on lambdas.[&]
captures can be dangerous if the lambda is called later (e.g., on another thread). The recommendation is to capture only what you need, by value where possible – consistent across all..h
for headers and.cpp
for implementation files by default (SF: Source files – C++) (SF: Source files – C++), but also say consistency in a project is more important than the specific extension. Google uses.h
for headers and.cc
for sources. This is a minor difference in convention (Google’s use of.cc
vs “.cpp” is just a style choice). Core and Google both agree filenames should be all lower-case. Core doesn’t mention underscores vs dashes explicitly, but consistency is implied..h
,.hpp
, or.hxx
(Guidelines for the use of the C++14 language in critical and safety-related systems) (and expects consistency). Source files typically use.c
for C and something like.cpp
or.cxx
for C++ (AUTOSAR doesn’t mandate one, but.cpp
is common). Google’s preference for.cc
is not used in AUTOSAR contexts (not a technical issue, just convention). Filenames in AUTOSAR are also lower-case (often with underscores)..cc
vs.cpp
), which is a matter of project style – marked partial but it’s a trivial convention difference.MyTypeName
vs a core-guidelines style ofmy_type_name
is a stylistic clash. Core acknowledges that naming style is arbitrary but requires consistency – their examples (e.g., in guidelines and STL) tend to use lower-case types.MyConcreteClass
(PascalCase). Core: tends towardmy_concrete_class
(following STL conventions) – or at least Core doesn’t insist on PascalCase. AUTOSAR is agnostic but often follows general C++ trends. This is primarily a style divergence: Google’s style guide and many internal codebases use PascalCase for types, whereas the C++ Core Guidelines favor a more STL-like all-lowercase approach.std::integral
). It’s likely core would recommend following the standard’s convention for concepts (i.e., snake_case). Thus, Google’sSameAs
vs. core’s expectedsame_as
is a conflict in naming style.Sortable
), treating them as types. This differs from the standard library and likely core style, which use snake_case (e.g.,sortable
) for concepts. AUTOSAR currently doesn’t support concepts at all (C++14), so any usage is non-compliant. In summary, Google’s concept naming style doesn’t match the lower_case style that core/standard favor, and AUTOSAR can’t use concepts in its current standard.snake_case
for variables (Google C++ Style Guide). Core Guidelines also prefer lowercase (likely snake_case) for variable names – this aligns. The difference: Google requires a trailing underscore for class data members (foo_
for a member vsfoo
for a local) (Google C++ Style Guide) (Google C++ Style Guide). Core Guidelines do not mandate a member naming convention like trailing underscore; they leave it to project style. Some core-guideline-following projects might usem_
or no prefix at all. So the general casing aligns (lowercase), but the member suffix is a Google-specific convention.mVariable
or_variable
or no notation, depending on legacy or team preference. Google’s trailing underscore for private members is not universally practiced in AUTOSAR space. However, this is just an naming style detail. The basic lowercase underscore style is common ground.lower_case_with_underscores
for variable names. Google adds a_
suffix for class data members (to distinguish them) (Google C++ Style Guide). Core/AUTOSAR don’t require that, though it’s allowed. So, naming case is aligned (snake_case), but the member-variable underscore suffix is a Google-specific style.constexpr
orconst
variables)k
(e.g.,kMaxValue
) (Google C++ Style Guide). Core Guidelines do not prescribe this convention. In fact, Core suggests that macros be ALL_CAPS and other constants follow normal variable naming (or use uppercase only if they are immutable and want to distinguish, but this is not in the guidelines explicitly). The STL and most C++ code do not use ak
prefix for constants. Thus, Google’s constant naming (sometimes called “Hungarian-ish” by others) is a unique style.constexpr
is available, they might just treat it as a variable. There is no single rule – just be consistent. Google’skName
style is not required in AUTOSAR, but it’s not harmful either. It’s simply different.k
prefix (e.g.,kBufferSize
) for constants and constexprs that have static storage duration (Google C++ Style Guide). Core/AUTOSAR do not use this convention (they either use ALL_CAPS for macros or just treat constant variables like other variables). This is a stylistic conflict – Google’s convention vs others. (All agree these constants should beconst
/constexpr
and not macros; only the naming differs.)DoSomethingImportant()
(CapitalizedCamelCase) (Google C++ Style Guide) (Google C++ Style Guide). Core: tends towarddo_something_important()
(lower_case). AUTOSAR: no enforced rule, but many codebases use lower_case or mixedCase for functions. So, Google’s function naming convention is a different style from core’s default and some AUTOSAR practices. This is a pure naming-style difference (no functional impact).my_project::sub_module
) (Google C++ Style Guide), which is common practice and not contradicted by core or AUTOSAR.diagnostic
orcalibration
. This matches Google’s requirement. Underscores in namespace names are also acceptable if needed (AUTOSAR doesn’t forbid it).kEnumName
style (Google C++ Style Guide) (for scoped and unscoped enums). Core Guidelines don’t have a stated convention, but the prevailing style in modern C++ is to treat enumerator names as scoped members, often lowercase (especially forenum class
). The standard library’s fewenum class
(likestd::endian
) use enumerators likelittle
andbig
(lowercase). Core’s NL.9 says ALL_CAPS only for macros, implying they wouldn’t use leadingk
or all-caps for enum values – probably just treat them as regular names (possibly PascalCase without thek
or just lower_case). In any case, Google’s prefixedkName
is unique to their style.enum class
, that practice is less necessary. AUTOSAR hasn’t mandated thek
prefix. Some AUTOSAR code might use ALL_CAPS for unscoped enum values to distinguish them. In scoped enums, they might use PascalCase or lower_case. There isn’t a single rule; it’s typically project-defined. Google’s approach differs (they don’t use ALL_CAPS, but usek
+ CamelCase which is distinct).kEnumValue
naming (Google C++ Style Guide), which differs from many other code standards. Core/AUTOSAR don’t prescribek
or all-caps for enum values – styles vary (older code uses ALL_CAPS, modern code often treats scoped enums like normal names). This is a naming convention conflict. (All agree enumerators should be constants – the difference is purely in notation: Google’s constant-style prefix vs. others’ conventions.)MYPROJECT_MY_MACRO
. There’s no conflict here.FILE_NAME_H_
or have a project prefix. Any function-like macros (which AUTOSAR tries to avoid) would also be all-caps. Google’s exampleMYPROJECT_ROUND(x)
(Google C++ Style Guide)fits this perfectly.Beta Was this translation helpful? Give feedback.
All reactions