음악, 삶, 개발

C++ Core Guidelines 목차 본문

개발 공부/C++ Core Guidelines

C++ Core Guidelines 목차

Lee_____ 2020. 9. 16. 18:52
In.0: Don’t panic!
P.1: Express ideas directly in code
P.2: Write in ISO Standard C++
P.3: Express intent
P.4: Ideally, a program should be statically type safe
P.5: Prefer compile-time checking to run-time checking
P.6: What cannot be checked at compile time should be checkable at run time
P.7: Catch run-time errors early
P.8: Don’t leak any resources
P.9: Don’t waste time or space
P.10: Prefer immutable data to mutable data
P.11: Encapsulate messy constructs, rather than spreading through the code
P.12: Use supporting tools as appropriate
P.13: Use support libraries as appropriate
I.1: Make interfaces explicit
I.2: Avoid non-const global variables
I.3: Avoid singletons
I.4: Make interfaces precisely and strongly typed
I.5: State preconditions (if any)
I.6: Prefer Expects() for expressing preconditions
I.7: State postconditions
I.8: Prefer Ensures() for expressing postconditions
I.9: If an interface is a template, document its parameters using concepts
I.10: Use exceptions to signal a failure to perform a required task
I.11: Never transfer ownership by a raw pointer (T*) or reference (T&)
I.12: Declare a pointer that must not be null as not_null
I.13: Do not pass an array as a single pointer
I.22: Avoid complex initialization of global objects
I.23: Keep the number of function arguments low
I.24: Avoid adjacent parameters of the same type when changing the argument order would change meaning
I.25: Prefer abstract classes as interfaces to class hierarchies
I.26: If you want a cross-compiler ABI, use a C-style subset
I.27: For stable library ABI, consider the Pimpl idiom
I.30: Encapsulate rule violations
F.1: “Package” meaningful operations as carefully named functions
F.2: A function should perform a single logical operation
F.3: Keep functions short and simple
F.4: If a function may have to be evaluated at compile time, declare it constexpr
F.5: If a function is very small and time-critical, declare it inline
F.6: If your function may not throw, declare it noexcept
F.7: For general use, take T* or T& arguments rather than smart pointers
F.8: Prefer pure functions
F.9: Unused parameters should be unnamed
F.15: Prefer simple and conventional ways of passing information
F.16: For “in” parameters, pass cheaply-copied types by value and others by reference to const
F.17: For “in-out” parameters, pass by reference to non-const
F.18: For “will-move-from” parameters, pass by X&& and std::move the parameter
F.19: For “forward” parameters, pass by TP&& and only std::forward the parameter
F.20: For “out” output values, prefer return values to output parameters
F.21: To return multiple “out” values, prefer returning a struct or tuple
F.22: Use T* or owner to designate a single object
F.23: Use a not_null to indicate that “null” is not a valid value
F.24: Use a span or a span_p to designate a half-open sequence
F.25: Use a zstring or a not_null to designate a C-style string
F.26: Use a unique_ptr to transfer ownership where a pointer is needed
F.27: Use a shared_ptr to share ownership
F.60: Prefer T* over T& when “no argument” is a valid option
F.42: Return a T* to indicate a position (only)
F.43: Never (directly or indirectly) return a pointer or a reference to a local object
F.44: Return a T& when copy is undesirable and “returning no object” isn’t needed
F.45: Don’t return a T&&
F.46: int is the return type for main()
F.47: Return T& from assignment operators
F.48: Don’t return std::move(local)
F.50: Use a lambda when a function won’t do (to capture local variables, or to write a local function)
F.51: Where there is a choice, prefer default arguments over overloading
F.52: Prefer capturing by reference in lambdas that will be used locally, including passed to algorithms
F.53: Avoid capturing by reference in lambdas that will be used non-locally, including returned, stored on the heap, or passed to another thread
F.54: If you capture this, capture all variables explicitly (no default capture)
F.55: Don’t use va_arg arguments
C.1: Organize related data into structures (structs or classes)
C.2: Use class if the class has an invariant; use struct if the data members can vary independently
C.3: Represent the distinction between an interface and an implementation using a class
C.4: Make a function a member only if it needs direct access to the representation of a class
C.5: Place helper functions in the same namespace as the class they support
C.7: Don’t define a class or enum and declare a variable of its type in the same statement
C.8: Use class rather than struct if any member is non-public
C.9: Minimize exposure of members
C.10: Prefer concrete types over class hierarchies
C.11: Make concrete types regular
C.20: If you can avoid defining default operations, do
C.21: If you define or =delete any copy, move, or destructor function, define or =delete them all
C.22: Make default operations consistent
C.30: Define a destructor if a class needs an explicit action at object destruction
C.31: All resources acquired by a class must be released by the class’s destructor
C.32: If a class has a raw pointer (T*) or reference (T&), consider whether it might be owning
C.33: If a class has an owning pointer member, define a destructor
C.35: A base class destructor should be either public and virtual, or protected and non-virtual
C.36: A destructor may not fail
C.37: Make destructors noexcept
C.40: Define a constructor if a class has an invariant
C.41: A constructor should create a fully initialized object
C.42: If a constructor cannot construct a valid object, throw an exception
C.43: Ensure that a copyable (value type) class has a default constructor
C.44: Prefer default constructors to be simple and non-throwing
C.45: Don’t define a default constructor that only initializes data members; use in-class member initializers instead
C.46: By default, declare single-argument constructors explicit
C.47: Define and initialize member variables in the order of member declaration
C.48: Prefer in-class initializers to member initializers in constructors for constant initializers
C.49: Prefer initialization to assignment in constructors
C.50: Use a factory function if you need “virtual behavior” during initialization
C.51: Use delegating constructors to represent common actions for all constructors of a class
C.52: Use inheriting constructors to import constructors into a derived class that does not need further explicit initialization
C.60: Make copy assignment non-virtual, take the parameter by const&, and return by non-const&
C.61: A copy operation should copy
C.62: Make copy assignment safe for self-assignment
C.63: Make move assignment non-virtual, take the parameter by &&, and return by non-const &
C.64: A move operation should move and leave its source in a valid state
C.65: Make move assignment safe for self-assignment
C.66: Make move operations noexcept
C.67: A polymorphic class should suppress copying
C.80: Use =default if you have to be explicit about using the default semantics
C.81: Use =delete when you want to disable default behavior (without wanting an alternative)
C.82: Don’t call virtual functions in constructors and destructors
C.83: For value-like types, consider providing a noexcept swap function
C.84: A swap function may not fail
C.85: Make swap noexcept
C.86: Make == symmetric with respect to operand types and noexcept
C.87: Beware of == on base classes
C.89: Make a hash noexcept
C.90: Rely on constructors and assignment operators, not memset and memcpy
C.100: Follow the STL when defining a container
C.101: Give a container value semantics
C.102: Give a container move operations
C.103: Give a container an initializer list constructor
C.104: Give a container a default constructor that sets it to empty
C.109: If a resource handle has pointer semantics, provide * and ->
C.120: Use class hierarchies to represent concepts with inherent hierarchical structure (only)
C.121: If a base class is used as an interface, make it a pure abstract class
C.122: Use abstract classes as interfaces when complete separation of interface and implementation is needed
C.126: An abstract class typically doesn’t need a constructor
C.127: A class with a virtual function should have a virtual or protected destructor
C.128: Virtual functions should specify exactly one of virtual, override, or final
C.129: When designing a class hierarchy, distinguish between implementation inheritance and interface inheritance
C.130: For making deep copies of polymorphic classes prefer a virtual clone function instead of copy construction/assignment
C.131: Avoid trivial getters and setters
C.132: Don’t make a function virtual without reason
C.133: Avoid protected data
C.134: Ensure all non-const data members have the same access level
C.135: Use multiple inheritance to represent multiple distinct interfaces
C.136: Use multiple inheritance to represent the union of implementation attributes
C.137: Use virtual bases to avoid overly general base classes
C.138: Create an overload set for a derived class and its bases with using
C.139: Use final on classes sparingly
C.140: Do not provide different default arguments for a virtual function and an overrider
C.145: Access polymorphic objects through pointers and references
C.146: Use dynamic_cast where class hierarchy navigation is unavoidable
C.147: Use dynamic_cast to a reference type when failure to find the required class is considered an error
C.148: Use dynamic_cast to a pointer type when failure to find the required class is considered a valid alternative
C.149: Use unique_ptr or shared_ptr to avoid forgetting to delete objects created using new
C.150: Use make_unique() to construct objects owned by unique_ptrs
C.151: Use make_shared() to construct objects owned by shared_ptrs
C.152: Never assign a pointer to an array of derived class objects to a pointer to its base
C.153: Prefer virtual function to casting
C.160: Define operators primarily to mimic conventional usage
C.161: Use non-member functions for symmetric operators
C.162: Overload operations that are roughly equivalent
C.163: Overload only for operations that are roughly equivalent
C.164: Avoid implicit conversion operators
C.165: Use using for customization points
C.166: Overload unary & only as part of a system of smart pointers and references
C.167: Use an operator for an operation with its conventional meaning
C.168: Define overloaded operators in the namespace of their operands
C.170: If you feel like overloading a lambda, use a generic lambda
C.180: Use unions to save memory
C.181: Avoid “naked” unions
C.182: Use anonymous unions to implement tagged unions
C.183: Don’t use a union for type punning
Enum.1: Prefer enumerations over macros
Enum.2: Use enumerations to represent sets of related named constants
Enum.3: Prefer class enums over “plain” enums
Enum.4: Define operations on enumerations for safe and simple use
Enum.5: Don’t use ALL_CAPS for enumerators
Enum.6: Avoid unnamed enumerations
Enum.7: Specify the underlying type of an enumeration only when necessary
Enum.8: Specify enumerator values only when necessary
R.1: Manage resources automatically using resource handles and RAII (Resource Acquisition Is Initialization)
R.2: In interfaces, use raw pointers to denote individual objects (only)
R.3: A raw pointer (a T*) is non-owning
R.4: A raw reference (a T&) is non-owning
R.5: Prefer scoped objects, don’t heap-allocate unnecessarily
R.6: Avoid non-const global variables
R.10: Avoid malloc() and free()
R.11: Avoid calling new and delete explicitly
R.12: Immediately give the result of an explicit resource allocation to a manager object
R.13: Perform at most one explicit resource allocation in a single expression statement
R.14: Avoid [] parameters, prefer span
R.15: Always overload matched allocation/deallocation pairs
R.20: Use unique_ptr or shared_ptr to represent ownership
R.21: Prefer unique_ptr over shared_ptr unless you need to share ownership
R.22: Use make_shared() to make shared_ptrs
R.23: Use make_unique() to make unique_ptrs
R.24: Use std::weak_ptr to break cycles of shared_ptrs
R.30: Take smart pointers as parameters only to explicitly express lifetime semantics
R.31: If you have non-std smart pointers, follow the basic pattern from std
R.32: Take a unique_ptr parameter to express that a function assumes ownership of a widget
R.33: Take a unique_ptr& parameter to express that a function reseats thewidget
R.34: Take a shared_ptr parameter to express that a function is part owner
R.35: Take a shared_ptr& parameter to express that a function might reseat the shared pointer
R.36: Take a const shared_ptr& parameter to express that it might retain a reference count to the object ???
R.37: Do not pass a pointer or reference obtained from an aliased smart pointer
ES.1: Prefer the standard library to other libraries and to “handcrafted code”
ES.2: Prefer suitable abstractions to direct use of language features
ES.5: Keep scopes small
ES.6: Declare names in for-statement initializers and conditions to limit scope
ES.7: Keep common and local names short, and keep uncommon and non-local names longer
ES.8: Avoid similar-looking names
ES.9: Avoid ALL_CAPS names
ES.10: Declare one name (only) per declaration
ES.11: Use auto to avoid redundant repetition of type names
ES.12: Do not reuse names in nested scopes
ES.20: Always initialize an object
ES.21: Don’t introduce a variable (or constant) before you need to use it
ES.22: Don’t declare a variable until you have a value to initialize it with
ES.23: Prefer the {}-initializer syntax
ES.24: Use a unique_ptr to hold pointers
ES.25: Declare an object const or constexpr unless you want to modify its value later on
ES.26: Don’t use a variable for two unrelated purposes
ES.27: Use std::array or stack_array for arrays on the stack
ES.28: Use lambdas for complex initialization, especially of const variables
ES.30: Don’t use macros for program text manipulation
ES.31: Don’t use macros for constants or “functions”
ES.32: Use ALL_CAPS for all macro names
ES.33: If you must use macros, give them unique names
ES.34: Don’t define a (C-style) variadic function
ES.40: Avoid complicated expressions
ES.41: If in doubt about operator precedence, parenthesize
ES.42: Keep use of pointers simple and straightforward
ES.43: Avoid expressions with undefined order of evaluation
ES.44: Don’t depend on order of evaluation of function arguments
ES.45: Avoid “magic constants”; use symbolic constants
ES.46: Avoid lossy (narrowing, truncating) arithmetic conversions
ES.47: Use nullptr rather than 0 or NULL
ES.48: Avoid casts
ES.49: If you must use a cast, use a named cast
ES.50: Don’t cast away const
ES.55: Avoid the need for range checking
ES.56: Write std::move() only when you need to explicitly move an object to another scope
ES.60: Avoid new and delete outside resource management functions
ES.61: Delete arrays using delete[] and non-arrays using delete
ES.62: Don’t compare pointers into different arrays
ES.63: Don’t slice
ES.64: Use the T{e}notation for construction
ES.65: Don’t dereference an invalid pointer
ES.70: Prefer a switch-statement to an if-statement when there is a choice
ES.71: Prefer a range-for-statement to a for-statement when there is a choice
ES.72: Prefer a for-statement to a while-statement when there is an obvious loop variable
ES.73: Prefer a while-statement to a for-statement when there is no obvious loop variable
ES.74: Prefer to declare a loop variable in the initializer part of a for-statement
ES.75: Avoid do-statements
ES.76: Avoid goto
ES.77: Minimize the use of break and continue in loops
ES.78: Don’t rely on implicit fallthrough in switch statements
ES.79: Use default to handle common cases (only)
ES.84: Don’t try to declare a local variable with no name
ES.85: Make empty statements visible
ES.86: Avoid modifying loop control variables inside the body of raw for-loops
ES.87: Don’t add redundant == or != to conditions
ES.100: Don’t mix signed and unsigned arithmetic
ES.101: Use unsigned types for bit manipulation
ES.102: Use signed types for arithmetic
ES.103: Don’t overflow
ES.104: Don’t underflow
ES.105: Don’t divide by zero
ES.106: Don’t try to avoid negative values by using unsigned
ES.107: Don’t use unsigned for subscripts, prefer gsl::index
Per.1: Don’t optimize without reason
Per.2: Don’t optimize prematurely
Per.3: Don’t optimize something that’s not performance critical
Per.4: Don’t assume that complicated code is necessarily faster than simple code
Per.5: Don’t assume that low-level code is necessarily faster than high-level code
Per.6: Don ’t make claims about performance without measurements
Per.7: Design to enable optimization
Per.10: Rely on the static type system
Per.11: Move computation from run time to compile time
Per.12: Eliminate redundant aliases
Per.13: Eliminate redundant indirections
Per.14: Minimize the number of allocations and deallocations
Per.15: Do not allocate on a critical branch
Per.16: Use compact data structures
Per.17: Declare the most used member of a time-critical struct first
Per.18: Space is time
Per.19: Access memory predictably
Per.30: Avoid context switches on the critical path
CP.1: Assume that your code will run as part of a multi-threaded program
CP.2: Avoid data races
CP.3: Minimize explicit sharing of writable data
CP.4: Think in terms of tasks, rather than threads
CP.8: Don’t try to use volatile for synchronization
CP.9: Whenever feasible use tools to validate your concurrent code
CP.20: Use RAII, never plain lock()/unlock()
CP.21: Use std::lock() or std::scoped_lock to acquire multiple mutexes
CP.22: Never call unknown code while holding a lock (e.g., a callback)
CP.23: Think of a joining thread as a scoped container
CP.24: Think of a thread as a global container
CP.25: Prefer gsl::joining_thread over std::thread
CP.26: Don’t detach() a thread
CP.31: Pass small amounts of data between threads by value, rather than by reference or pointer
CP.32: To share ownership between unrelated threads use shared_ptr
CP.40: Minimize context switching
CP.41: Minimize thread creation and destruction
CP.42: Don’t wait without a condition
CP.43: Minimize time spent in a critical section
CP.44: Remember to name your lock_guards and unique_locks
CP.50: Define a mutex together with the data it guards. Use synchronized_value where possible
CP.60: Use a future to return a value from a concurrent task
CP.61: Use async() to spawn concurrent tasks
CP.100: Don’t use lock-free programming unless you absolutely have to
CP.101: Distrust your hardware/compiler combination
CP.102: Carefully study the literature
CP.110: Do not write your own double-checked locking for initialization
CP.111: Use a conventional pattern if you really need double-checked locking
CP.200: Use volatile only to talk to non-C++ memory
CP.201: ??? Signals
E.1: Develop an error-handling strategy early in a design
E.2: Throw an exception to signal that a function can’t perform its assigned task
E.3: Use exceptions for error handling only
E.4: Design your error-handling strategy around invariants
E.5: Let a constructor establish an invariant, and throw if it cannot
E.6: Use RAII to prevent leaks
E.7: State your preconditions
E.8: State your postconditions
E.12: Use noexcept when exiting a function because of a throw is impossible or unacceptable
E.13: Never throw while being the direct owner of an object
E.14: Use purpose-designed user-defined types as exceptions (not built-in types)
E.15: Catch exceptions from a hierarchy by reference
E.16: Destructors, deallocation, and swap must never fail
E.17: Don’t try to catch every exception in every function
E.18: Minimize the use of explicit try/catch
E.19: Use a final_action object to express cleanup if no suitable resource handle is available
E.25: If you can’t throw exceptions, simulate RAII for resource management
E.26: If you can ’t throw exceptions, consider failing fast
E.27: If you can’t throw exceptions, use error codes systematically
E.28: Avoid error handling based on global state (e.g. errno)
E.30: Don’t use exception specifications
E.31: Properly order your catch-clauses
Con.1: By default, make objects immutable
Con.2: By default, make member functions const
Con.3: By default, pass pointers and references to consts
Con.4: Use const to define objects with values that do not change after construction
Con.5: Use constexpr for values that can be computed at compile time
T.1: Use templates to raise the level of abstraction of code
T.2: Use templates to express algorithms that apply to many argument types
T.3: Use templates to express containers and ranges
T.4: Use templates to express syntax tree manipulation
T.5: Combine generic and OO techniques to amplify their strengths, not their costs
T.10: Specify concepts for all template arguments
T.11: Whenever possible use standard concepts
T.12: Prefer concept names over auto for local variables
T.13: Prefer the shorthand notation for simple, single-type argument concepts
T.20: Avoid “concepts” without meaningful semantics
T.21: Require a complete set of operations for a concept
T.22: Specify axioms for concepts
T.23: Differentiate a refined concept from its more general case by adding new use patterns.
T.24: Use tag classes or traits to differentiate concepts that differ only in semantics.
T.25: Avoid complementary constraints
T.26: Prefer to define concepts in terms of use-patterns rather than simple syntax
T.40: Use function objects to pass operations to algorithms
T.41: Require only essential properties in a template’s concepts
T.42: Use template aliases to simplify notation and hide implementation details
T.43: Prefer using over typedef for defining aliases
T.44: Use function templates to deduce class template argument types (where feasible)
T.46: Require template arguments to be at least Regular or SemiRegular
T.47: Avoid highly visible unconstrained templates with common names
T.48: If your compiler does not support concepts, fake them with enable_if
T.49: Where possible, avoid type-erasure
T.60: Minimize a template ’s context dependencies
T.61: Do not over-parameterize members (SCARY)
T.62: Place non-dependent class template members in a non-templated base class
T.64: Use specialization to provide alternative implementations of class templates
T.65: Use tag dispatch to provide alternative implementations of a function
T.67: Use specialization to provide alternative implementations for irregular types
T.68: Use {} rather than () within templates to avoid ambiguities
T.69: Inside a template, don’t make an unqualified non-member function call unless you intend it to be a customization point
T.80: Do not naively templatize a class hierarchy
T.81: Do not mix hierarchies and arrays
T.82: Linearize a hierarchy when virtual functions are undesirable
T.83: Do not declare a member function template virtual
T.84: Use a non-template core implementation to provide an ABI-stable interface
T.100: Use variadic templates when you need a function that takes a variable number of arguments of a variety of types
T.101: ??? How to pass arguments to a variadic template ???
T.102: How to process arguments to a variadic template
T.103: Don’t use variadic templates for homogeneous argument lists
T.120: Use template metaprogramming only when you really need to
T.121: Use template metaprogramming primarily to emulate concepts
T.122: Use templates (usually template aliases) to compute types at compile time
T.123: Use constexpr functions to compute values at compile time
T.124: Prefer to use standard-library TMP facilities
T.125: If you need to go beyond the standard-library TMP facilities, use an existing library
T.140: Name all operations with potential for reuse
T.141: Use an unnamed lambda if you need a simple function object in one place only
T.142?: Use template variables to simplify notation
T.143: Don’t write unintentionally non-generic code
T.144: Don’t specialize function templates
T.150: Check that a class matches a concept using static_assert
CPL.1: Prefer C++ to C
CPL.2: If you must use C, use the common subset of C and C++, and compile the C code as C++
CPL.3: If you must use C for interfaces, use C++ in the calling code using such interfaces
SF.1: Use a .cpp suffix for code files and .h for interface files if your project doesn’t already follow another convention
SF.2: A .h file may not contain object definitions or non-inline function definitions
SF.3: Use .h files for all declarations used in multiple source files
SF.4: Include .h files before other declarations in a file
SF.5: A .cpp file must include the .h file(s) that defines its interface
SF.6: Use using namespace directives for transition, for foundation libraries (such as std), or within a local scope (only)
SF.7: Don’t write using namespace at global scope in a header file
SF.8: Use #include guards for all .h files
SF.9: Avoid cyclic dependencies among source files
SF.10: Avoid dependencies on implicitly #included names
SF.11: Header files should be self-contained
SF.12: Prefer the quoted form of #include for files relative to the including file and the angle bracket form everywhere else
SF.20: Use namespaces to express logical structure
SF.21: Don’t use an unnamed (anonymous) namespace in a header
SF.22: Use an unnamed (anonymous) namespace for all internal/non-exported entities
SL.1: Use libraries wherever possible
SL.2: Prefer the standard library to other libraries
SL.3: Do not add non-standard entities to namespace std
SL.4: Use the standard library in a type-safe manner
SL.con.1: Prefer using STL array or vector instead of a C array
SL.con.2: Prefer using STL vector by default unless you have a reason to use a different container
SL.con.3: Avoid bounds errors
SL.con.4: don’t use memset or memcpy for arguments that are not trivially-copyable
SL.str.1: Use std::string to own character sequences
SL.str.2: Use std::string_view or gsl::string_span to refer to character sequences
SL.str.3: Use zstring or czstring to refer to a C-style, zero-terminated, sequence of characters
SL.str.4: Use char* to refer to a single character
SL.str.5: Use std::byte to refer to byte values that do not necessarily represent characters
SL.str.10: Use std::string when you need to perform locale-sensitive string operations
SL.str.11: Use gsl::string_span rather than std::string_view when you need to mutate a string
SL.str.12: Use the s suffix for string literals meant to be standard-library strings
SL.io.1: Use character-level input only when you have to
SL.io.2: When reading, always consider ill-formed input
SL.io.3: Prefer iostreams for I/O
SL.io.10: Unless you use printf-family functions call ios_base::sync_with_stdio(false)
SL.io.50: Avoid endl
SL.C.1: Don’t use setjmp/longjmp
A.1: Separate stable code from less stable code
A.2: Express potentially reusable parts as a library
A.4: There should be no cycles among libraries
NR.1: Don’t insist that all declarations should be at the top of a function
NR.2: Don’t insist to have only a single return-statement in a function
NR.3: Don’t avoid exceptions
NR.4: Don’t insist on placing each class declaration in its own source file
NR.5: Don’t use two-phase initialization
NR.6: Don’t place all cleanup actions at the end of a function and goto exit
NR.7: Don’t make all data members protected
GSL.ptr: Smart pointer concepts
NL.1: Don’t say in comments what can be clearly stated in code
NL.2: State intent in comments
NL.3: Keep comments crisp
NL.4: Maintain a consistent indentation style
NL.5: Avoid encoding type information in names
NL.7: Make the length of a name roughly proportional to the length of its scope
NL.8: Use a consistent naming style
NL.9: Use ALL_CAPS for macro names only
NL.10: Prefer underscore_style names
NL.11: Make literals readable
NL.15: Use spaces sparingly
NL.16: Use a conventional class member declaration order
NL.17: Use K&R-derived layout
NL.18: Use C++-style declarator layout
NL.19: Avoid names that are easily misread
NL.20: Don’t place two statements on the same line
NL.21: Declare one name (only) per declaration
NL.25: Don’t use void as an argument type
NL.26: Use conventional const notation
FAQ.1: What do these guidelines aim to achieve?
FAQ.2: When and where was this work first announced?
FAQ.3: Who are the authors and maintainers of these guidelines?
FAQ.4: How can I contribute?
FAQ.5: How can I become an editor/maintainer?
FAQ.6: Have these guidelines been approved by the ISO C++ standards committee? Do they represent the consensus of the committee?
FAQ.7: If these guidelines are not approved by the committee, why are they under github.com/isocpp?
FAQ.8: Will there be a C++98 version of these Guidelines? a C++11 version?
FAQ.9: Do these guidelines propose new language features?
FAQ.10: What version of Markdown do these guidelines use?
FAQ.50: What is the GSL (guidelines support library)?
FAQ.51: Is github.com/Microsoft/GSL the GSL?
FAQ.52: Why not supply an actual GSL implementation in/with these guidelines?
FAQ.53: Why weren ’t the GSL types proposed through Boost?
FAQ.54: Has the GSL (guidelines support library) been approved by the ISO C++ standards committee?
FAQ.55: If you’re using the standard types where available, why is the GSL string_span different from the string_view in the Library Fundamentals 1 Technical Specification and C++17 Working Paper? Why not just use the committee-approved string_view?
FAQ.56: Is owner the same as the proposed observer_ptr?
FAQ.57: Is stack_array the same as the standard array?
FAQ.58: Is dyn_array the same as vector or the proposed dynarray?
FAQ.59: Is Expects the same as assert?
FAQ.60: Is Ensures the same as assert?
Discussion: Define and initialize member variables in the order of member declaration
Discussion: Use of =, {}, and () as initializers
Discussion: Use a factory function if you need “virtual behavior” during initialization
Discussion: Make base class destructors public and virtual, or protected and non-virtual
Discussion: Usage of noexcept
Discussion: Destructors, deallocation, and swap must never fail
Discussion: Provide strong resource safety; that is, never leak anything that you think of as a resource
Discussion: Never throw while holding a resource not owned by a handle
Discussion: A “raw” pointer or reference is never a resource handle
Discussion: Never let a pointer outlive the object it points to
Discussion: Use templates to express containers (and other resource handles)
Discussion: Return containers by value (relying on move or copy elision for efficiency)
Discussion: If a class is a resource handle, it needs a constructor, a destructor, and copy and/or move operations
Discussion: If a class is a container, give it an initializer-list constructor
Tools: Clang-tidy
Tools: CppCoreCheck