Skip to content

Latest commit

 

History

History
89 lines (86 loc) · 21.1 KB

cpp_core_guidelines.md

File metadata and controls

89 lines (86 loc) · 21.1 KB
  1. First column = Guildeline name = Link to the rule in the master branch of the Git repository of CppCoreGuidelines
  2. Second column = Summary (one short line)
    • If you do not understand the Summary => Spend more time reading the rule
    • If you think the Summary can be improved => Please edit this file :-)
    • If the Summary is "???" => There is not (yet) a summary => Please provide a summary :-)
  3. Third column = Acceptation = Position of developers (Yes, Yes but..., Optional, No because..., No way)
Guildeline name Summary Acceptation
P.1: Express ideas directly in code Replace anonymous int by functional EventID Yes
P.2: Write in ISO Standard C++ No Visual/GNU C++ extensions Yes
P.3: Express intent Code for the other devs, Self-explanatory code does not need comments Yes
P.4: Ideally, a program should be statically type safe Replace union -> variant and int array[5] -> span Yes
P.5: Prefer compile-time checking to run-time checking Replace assert by static_assert when possible Yes
P.6: What cannot be checked at compile time should be checkable at run time Use span Developer decides, reviewer may propose to use span
P.7: Catch run-time errors early ??? (please provide a summary) Yes
P.8: Don't leak any resources Use RAII Yes
P.9: Don't waste time or space C++ => Do not sacrify performance Yes
P.10: Prefer immutable data to mutable data Use constants when possible (see section Constants and Immutability) Ok
I.1: Make interfaces explicit Names (of function/variable...) must convey semantic (no surprise when used) Yes
I.2 Avoid global variables Global variable hide dependencies (except const). Put log level in an object. Yes but except specific cases (justify)
I.3: Avoid singletons Singleton is a global variable => Singleton also hides dependencies Yes but as above (see Dependency Inversion)
I.4: Make interfaces precisely and strongly typed No anonymous int or void* (no error-prone casting). Use instead variant, base class, template (and C++17 Concept). Yes. Use setter (SBE) instead of many default arg.
I.5: State preconditions (if any) Provide comments for preconditions and use Expects(), static_assert(), assert(), if()... Yes
I.6: Prefer Expects() for expressing preconditions Expects() = Make it clear + Enable analysis tools No Expects() on release => assert() static_assert(). Integrity check => if()
I.7: State postconditions Same as for preconditions Yes
I.8: Prefer Ensures() for expressing postconditions Same as for preconditions No, same remark as I.6
I.9: If an interface is a template, document its parameters using concepts Use C++17 Concepts (available in gcc-6.1). In comments if not yet supported. No, Document in Doxygen if not supported yes)
I.10: Use exceptions to signal a failure to perform a required task Prevent error silence because system may become unexpected => Throw exception or return error status (or a pair {result + error}). Exceptions in framework. Logs in application Yes
I.11: Never transfer ownership by a raw pointer (T*) Avoid ownnership transfer. => Use smart_pointer(unique_ptr or shared_ptr) to pass ownership. => Use owner(GSL) in older code. Yes
I.12: Declare a pointer that must not be null as not_null To avoid nullptr deferencing errors and redundant checks for nullptr. Yes
I.13: Do not pass an array as a single pointer Use span and string_span to avoid range error Developer decides, reviewer may propose to use span
I.22: Avoid complex initialization of global objects Avoid globals(namespace scope) object altogether Yes
I.23: Keep the number of function arguments low Avoid more than 8 arguments. Group arguments into meaningfull objects or use default arguments Yes
I.24: Avoid adjacent unrelated parameters of the same type Pass object representing a range (span). Define struct as parameter type Yes
I.25: Prefer abstract classes as interfaces to class hierarchies Use abstract class with pure virtual function Yes
I.26: If you want a cross-compiler ABI, use a C-style subset Different compilers implement different binary layouts Not concerned
F.1: "Package" meaningful operations as carefully named functions functions can be easier to reuse than objects Yes
F.2: A function should perform a single logical operation simpler to understand, test and reuse Yes
F.4: If a function may have to be evaluated at compile time, declare it constexpr contexpr is needed to tell the compiler to allow compile-time evaluation Yes
F.18: For "consume" parameters, pass by X&& and std::move the parameter avoids a deep copy and sometimes a copy would not have been possible (for ex. std::ofstream) Yes
F.60: Prefer T* over T& when "no argument" is a valid option A pointer (T*) can be a nullptr and a reference (T&) cannot Yes
[F.42: Return a T* to indicate a position (only)] (https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#f42-return-a-t-to-indicate-a-position-only) That's what pointers are good for. Returning a T* to transfer ownership is a misuse Yes
[F.52: Prefer capturing by reference in lambdas that will be used locally, including passed to algorithms] (https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#f52-prefer-capturing-by-reference-in-lambdas-that-will-be-used-locally-including-passed-to-algorithms) know capture options Yes
F.16: For "in" parameters, pass cheaply-copied types by value and others by reference to const Same semantics for both, better performances Yes
F.21: To return multiple "out" values, prefer returning a tuple or struct It is self documenting, and std::ignore can be sued To bench
F.26: Use a unique_ptr to transfer ownership where a pointer is needed Use std::unique_ptr to ransfer ownership Yes if code is C++11 only
F.43: Never (directly or indirectly) return a pointer to a local object Do not return pointers to local object Yes
F.44: Return a T& when copy is undesirable and "returning no object" isn't needed Return T& when copy is undesirable Yes
F.45: Don't return a T&& Do not return T&&, it makes no sense Yes
F.46: int is the return type for main() void main() is not C++ Yes
F.47: Return T& from assignment operators Ensures consistency with std Yes
F.50: Use a lambda when a function won't do (to capture local variables, or to write a local function) Same as a function object but more simple to write Yes
F.51: Where there is a choice, prefer default arguments over overloading Limits code duplication and behavior divergence No
F.53: Avoid capturing by reference in lambdas that will be used nonlocally, including returned, stored on the heap, or passed to another thread To maintain proper lifecycle Yes
F.54: If you capture this, capture all variables explicitly (no default capture) Default capture does no behave the same for local variable and data members To bench
C.1: Organize related data into structures (structs or classes) Ex: x and y i n a class "Point" OK
C.2: Use class if the class has an invariant; use struct if the data members can vary independently Readability, hints at invariants OK
C.3: Represent the distinction between an interface and an implementation using a class ??? Ok on principle
C.4: Make a function a member only if it needs direct access to the representation of a class Free function should not be tied to a class for no reason OK
C.5: Place helper functions in the same namespace as the class they support Profit from argument dependent lookup OK
C.7: Don't define a class or enum and declare a variable of its type in the same statement Useless and confusing for readers OK
C.8: use class rather that struct if any member is non-public Hint readers OK
C.9: minimize exposure of members Improves encapsulation OK
C.10 Prefer a concrete type over more complicated classes More simple than a class hierarchy Unclear
C.11: Make concrete types regular Thats is, behave with a value semantics. Easier to use. Unclear
C.20: If you can avoid defining default operations, do Shorter code Yes, and do not reimplement defaults
C.21: If you define or =delete any default operation, define or =delete them all To ensure proper semantics are used Yes
C.22: Make default operations consistent Doing otherwise would be most confusing Yes
C.30: Define a destructor if a class needs an explicit action at object destruction When something must be done at destruction, the destructor must do it Yes
C.31: All resources acquired by a class must be released by the class's destructor Basis of RAII Yes
C.32: If a class has a raw pointer (T*) or reference (T&), consider whether it might be owning Annotate pointer as owning or not OK but avoid owning reference
C.33: If a class has an owning pointer member, define a destructor If using pointers as members, protect from leak/copy OK
C.34: If a class has an owning reference member, define a destructor Same as for pointer Prefer avoid owning reference, else Yes
C.35: A base class destructor should be either public and virtual, or protected and nonvirtual Avoid leak of derived classes members Prefer avoid owning reference, else Yes
C.36: A destructor may not fail RAII safe OK
C.37: Make destructors noexcept Be explicit on exception absence OK
C.40: Define a constructor if a class has an invariant In Out principle OK
C.41: A constructor should create a fully initialized object Be safe with invariant and public interface OK
C.42: If a constructor cannot construct a valid object, throw an exception Avoid objects in crashed state OK
C.43: Ensure that a class has a default constructor Allow default object whenever possible For value classes
C.44: Prefer default constructors to be simple and non-throwing Be safe with default constructors OK
C.45: Don't define a default constructor that only initializes data members; use in-class member initializers instead Less code better OK
C.46: By default, declare single-argument constructors explicit Avoid false conversions OK
C.47: Define and initialize member variables in the order of member declaration Respect members order OK