The C++ Core Guidelines are a set of tried-and-true guidelines, rules, and best practices about coding in C++

Overview

C++ Core Guidelines

"Within C++ is a smaller, simpler, safer language struggling to get out." -- Bjarne Stroustrup

The C++ Core Guidelines are a collaborative effort led by Bjarne Stroustrup, much like the C++ language itself. They are the result of many person-years of discussion and design across a number of organizations. Their design encourages general applicability and broad adoption but they can be freely copied and modified to meet your organization's needs.

Getting started

The guidelines themselves are found at CppCoreGuidelines. The document is in GH-flavored MarkDown. It is intentionally kept simple, mostly in ASCII, to allow automatic post-processing such as language translation and reformatting. The editors maintain one version formatted for browsing. Note that it is manually integrated and can be slightly older than the version in the master branch.

The Guidelines are a constantly evolving document without a strict "release" cadence. Bjarne Stroustrup periodically reviews the document and increments the version number in the introduction. Checkins that increment the version number are tagged in git.

Many of the guidelines make use of the header-only Guidelines Support Library. One implementation is available at GSL: Guidelines Support Library.

Background and scope

The aim of the guidelines is to help people to use modern C++ effectively. By "modern C++" we mean C++11, C++14, and C++17. In other words, what would you like your code to look like in 5 years' time, given that you can start now? In 10 years' time?

The guidelines are focused on relatively higher-level issues, such as interfaces, resource management, memory management, and concurrency. Such rules affect application architecture and library design. Following the rules will lead to code that is statically type-safe, has no resource leaks, and catches many more programming logic errors than is common in code today. And it will run fast -- you can afford to do things right.

We are less concerned with low-level issues, such as naming conventions and indentation style. However, no topic that can help a programmer is out of bounds.

Our initial set of rules emphasizes safety (of various forms) and simplicity. They may very well be too strict. We expect to have to introduce more exceptions to better accommodate real-world needs. We also need more rules.

You will find some of the rules contrary to your expectations or even contrary to your experience. If we haven't suggested that you change your coding style in any way, we have failed! Please try to verify or disprove rules! In particular, we'd really like to have some of our rules backed up with measurements or better examples.

You will find some of the rules obvious or even trivial. Please remember that one purpose of a guideline is to help someone who is less experienced or coming from a different background or language to get up to speed.

The rules are designed to be supported by an analysis tool. Violations of rules will be flagged with references (or links) to the relevant rule. We do not expect you to memorize all the rules before trying to write code.

The rules are meant for gradual introduction into a code base. We plan to build tools for that and hope others will too.

Contributions and LICENSE

Comments and suggestions for improvements are most welcome. We plan to modify and extend this document as our understanding improves and the language and the set of available libraries improve. More details are found at CONTRIBUTING and LICENSE.

Thanks to DigitalOcean for hosting the Standard C++ Foundation website.

Comments
  • Renaming CP.25 raii_thread, and fixing CP.26 detached_thread

    Renaming CP.25 raii_thread, and fixing CP.26 detached_thread

    CP.25 raii_thread

    The PR for this is now ready to merge into GSL here: https://github.com/Microsoft/GSL/pull/504 IMO the design looks fine. But do we really want to use the name "raii_thread"? Yes, that's technically what it is (for those who like using that acronym), but why not "joining_thread" or "scoped_thread"? ... or, best of all, "thread"!

    Proposed resolution: Rename "raii_thread" to just gsl::thread. This type is what std::thread ought to have been, and it's identical to std::thread except that gsl::thread has a properly-joining destructor and does not have detach. And this is what namespaces are for. :)

    CP.26 detached_thread

    The GSL PR has split out "raii_thread" because I suggested "detached_thread" was problematic and less recommendable. So we should also do something about CP.26 which recommends "detached_thread" -- I think detaching is an antipattern we should not encourage, as Hans and others have pointed out many times (e.g., orderly shutdown is at best problematic and usually impossible).

    Proposed resolution:

    • Drop "gsl::detached_thread" and the current CP.26.
    • Replace CP.26 with the inverse Guideline that says "never detach threads" (that’s an unsafe antipattern). Include an example showing how you can never safely join or interact with it during static destruction. Enforcement: Flag any call to std::thread::detach. What to do instead: Just stick a normal gsl::thread in a global object or container and then ignore it if you want… but it means better more-orderly shutdown by default plus the ability to actually join with it if you do want to refer to it later.
    resolved 
    opened by hsutter 46
  • Proposal to outlaw std::endl

    Proposal to outlaw std::endl

    Writing a std::endl to a stream is exactly equivalent to writing a '\n', followed by a std::flush to a stream. In my experience very few people are aware of the later part and for some reason assume that it is instead a portable way to print a newline (which it technically is, but so is '\n'). Many of them are surprised, sometimes shocked, when they learn the truth, because they excessively use it in their codebase whenever they need a newline, thereby slowing down everything for no gain at all. (This is premature pessimization!)

    Even for people who are aware of the truth this can be a disadvantage because they have to find out whether the flush is really necessary in the particular place, or whether they can replace multiple writes with one.

    The following is similar to what I've seen in the wild:

    std::cout << "foo" << std::endl
              << "bar" << std::endl << std::endl
              << "baz" << std::endl;
    

    This can be replaced with

    std::cout << "foo\n"
                 "bar\n\n"
                 "baz\n";
    

    Which is just one write-call and additionally improves readability by reducing line-noise (this is even more true in editors that highlight escape-sequences).

    For the few cases where flushing is really desired, std::flush works perfectly well and actually states the intent:

    std::cout << "Some log-statement\n" << std::flush;
    
    resolved 
    opened by Florianjw 44
  • SF.12: Prefer the quoted form of `#include` for files relative to the…

    SF.12: Prefer the quoted form of `#include` for files relative to the…

    … including file

    The current guidance on SF.12 can be over-applied and devolves into "always use <>" because all compilers support adding include directories to the <> search. In this case, even the current directory may be added and so it is always possible to use <> for every header. Applying the guidance then devolves into an undesirable state where <> is always used and include"" is never used.

    Instead, the proposed guidance leverages and encourages the distinction between <> and "" to create an easy-to-understand rule that the original guidance hints at and that most developers already follow and understand: "" is for local headers and <> is for library and external headers.

    opened by apenn-msft 36
  • CP.8 is disturbing

    CP.8 is disturbing

    Would it be possible to replace this rule with something like:

    Use atomic loads and stores with memory_order_relaxed instead of volatile

    Reason: This describes the intent better, and makes the code well defined instead of implementation-defined

    opened by imre-palik 36
  • C.128 Hiding Functions and Implicit Virtual/Override Functions Are Common and Useful

    C.128 Hiding Functions and Implicit Virtual/Override Functions Are Common and Useful

    It is common to declare functions with the same name and different parameters in derived ~~functions~~ classes. A prominent example is the assignment operator, which typically has a parameter of the same type as the class where it is declared. It is not a mistake, but the pure intention. So reporting all and every hidden function yields a very high false positive rate.

    On the other hand there really may be unintentionally hidden functions. The important cases are those where a function in the derived class could accidentally be called instead of the one in the ~~derived~~ base class. This is only possible in 2 cases:

    • The base class function overloads are not introduced in the derived class definition with a using declaration ("hide-by-name") and all types of the parameter set (i.e. considering combinations of default parameters) of one function overload in the base class can implicitly be converted to the types of the parameter set of one function overload in the derived class,
    • The base class function overloads are introduced in the derived class definition with a using declaration ("hide-by-signature") and all types of the parameters of one function overload of the base class match exactly the types of the parameters of one function overload of the derived class.

    Furthermore, the guideline does not take into account that in some cases implicit overriding is useful and safe, for instance when the overridden function has no definition, which is frequently the case for interfaces (i.e. abstract classes with no non-static member function/variable definitions). Though the functions are technically overridden in the derived class, one would not consider this mechanism "overriding", but rather "implementing". Naturally adding override to all affected functions in the derived class does not make the intention any clearer. Also it would make turning a class into an interface implementation more bothersome because the developer would suddenly have to add override to all functions which now implement a function of the interface.

    Additionally, the guideline does not consider situations where it may still be useful to mark destructors with virtual. If a derived class adds new virtual functions, the intention that the destructor needs to be virtual for this class should be made clear, independently of a possible virtual base class destructor. This also conforms to guideline C.35.

    Moreover, the combination of virtual and final is actually useful because final does not necessarily imply overriding. This can be the case when a function shall be part of the polymorphic interface of a class, but shall already be final in the class where it is first declared. Accordingly, the combination of override and final is useful to state that a sealed function is indeed overriding another function and not a new virtual function.

    I suggest to replace the current guideline with a more meaningful one:

    • In case the overloads of functions with a certain name are not introduced in a derived class/struct with a using declaration ("hide-by-name"), there shall be no function overload in the derived class/struct which has a parameter set whose types can implicitly be converted from the types of a parameter set of a function overload in the base class/struct.
    • In case the overloads of functions with a certain name are introduced in a derived class/struct with a using declaration ("hide-by-signature"), there shall be no function overload in the derived class/struct whose parameter types match exactly the parameter types of a function overload in the base class/struct.
    • A function should be marked with override and should not be marked with virtual if it overrides a function ~~which has a definition~~ of a class which has a non-static member function with a definition (a class which is not an interface).
    • A function should be marked with neither override nor virtual if it overrides a function ~~which has no definition~~ of a class which has no definition for any of the non-static member functions (an interface). This rule has lower priority than the rule above in the case that a class derives from both, an interface and a non-interface class which both happen to have a virtual function with the same name and signature.
    • A destructor should be marked with virtual if and only if its containing class/struct adds new virtual functions, even if the base class/struct destructor is already virtual (in accordance with C.35). A destructor should never be marked with override.
    • The usage of final is untouched by the guideline because sealing a function does not always imply overriding another function. final only implies a virtual function, which can be both, a new virtual function (which always has to be marked with virtual) or an overriding function, for which the rules above apply.
    opened by BlackStarX42 29
  • Expand C.9: (Minimize exposure of members) for member functions

    Expand C.9: (Minimize exposure of members) for member functions

    Currently C.9 explains mainly how to handle member variables, but says nothing about member function.

    In particular I would like to add something like

    ##### Note
    
    Private non-virtual member function do expose implementation detail of the class.
    To avoid exposing those implementation detail, consider moving the implementation to the corresponding implementation file in an anonymous namespace.
    

    And as example something like

    header file (before)

    #include <optional>
    
    class C{
    int data;
    // ...
    private:
    std::optional<int> fun(); // optional used only here(!)
    }
    

    impl file (before)

    std::optional<int> C::fun(){
      return this->data == 42? std::nullopt : this->data;
    }
    

    and

    header file (after)

    class C{
    int data;
    // ...
    }
    

    impl file (after)

    #include <optional>
    namespace{
      std::optional<int> fun(int data){
        return data == 42? std::nullopt : data;
      }
    }
    

    and as enforcement "flag private non-virtual member functions"

    Benefits:

    • smaller header files, it is easier to recognize what the class does (for end-user)
    • generally means more stable API/ABI
    • faster build times, as potentially less includes and code to parse
    • potentially smaller binaries (especially if class is exported)
    • different optimization opportunities (especially if a class is exported from a library), with the second approach, compilers and tools for static analysis can diagnose much more easily if fun is dead code or not.
    • makes easier to set invariant, as those are normally set by the interface (public/protected functions), and it ensures by design that private member functions can not call public functions
    opened by fekir 26
  • Add an exception to ES.46 for contextual conversion to bool

    Add an exception to ES.46 for contextual conversion to bool

    Editors call: In Es.46, we should consider not flagging a conversion to bool used only to perform a boolean test (e.g., if (myint)). We do want to continue flagging attempts to convert to assign a boolean value (e.g., 'mybool = myint;should require anarrow`).

    opened by hsutter 24
  • Insufficient supporting arguments are given for why

    Insufficient supporting arguments are given for why "virtual void method() override" should be avoided

    https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#c128-virtual-functions-should-specify-exactly-one-of-virtual-override-or-final

    Insufficient supporting arguments are given for why "virtual void method() override" should be avoided. The "virtual" is of course not required, but our team believes it increases readability to always have virtual on the left for virtual methods (the "override" on the right might be scrolled off the screen or on a different line). If "override" could be moved over to the left like in C# that would be preferable (I assume it would break compatibility). Is someone able to add some convincing examples or additional reasons why the extra virtual should be avoided?

    opened by sean-mcmanus 24
  • SF.1: Default convention for C++ header files should be .hpp (matching .cpp)

    SF.1: Default convention for C++ header files should be .hpp (matching .cpp)

    Having a specific “.hpp“ extension (like Boost does) for C++ headers (matching the “.cpp“ extension) makes the C++-specific nature of the header very clear.

    Moreover, editors and tools can understand simply looking at the extension that it's a C++ header instead of a pure C header. In this way, rules like this one requesting a “magic string“ to clarify that an header is C++ (not C) are made useless:

    "The “-- C++ --” string on the first line is there to tell Emacs that the source file is a C++ file, not a C file (Emacs assumes .h files are C files by default)."

    The “.h” extension should be used for header files that contain pure C declarations, and are intended to be read by C and/or C++ (like <stdio.h>, <Windows.h>, or custom headers exposing pure C interfaces). The “.hpp” extension should be used for header files that contain C++ stuff (e.g.: class declarations and/or inline implementations) and are not intended for C.

    declined 
    opened by GiovanniDicanio 24
  • C.121: Recommend protected destructor for interfaces?

    C.121: Recommend protected destructor for interfaces?

    I like the technique from C.35 of using protected destructors to prevent destruction of pointers to base (for cases when such prevention is what you need). It seems to me that this would be an ideal technique for interfaces. Wouldn't it be a good idea to recommend protected destructors for interfaces in C.121, instead of the public virtual destructor that the example uses now?

    That would prevent clients from destroying a service by calling delete on a pointer to the service's interface. It would probably also prevent clients from putting interfaces into smart pointers (you should not own a service through it's interface).

    opened by hpenne 24
  • C.134 - Ensure all data members have the same access level - Does this deserve to be here?

    C.134 - Ensure all data members have the same access level - Does this deserve to be here?

    You know, I understand the reasoning behind this, but in my own practice it's just pointless 99% of the time and I end up undoing in those cases because I know very well that no one is ever going to inherit from the class in question. Sometimes a public member is a public member and I don't need to hide that behind annoying accessors/mutators. If trivial Java-esque things like this get put into the standard then I'm just going to disable the whole flagging/warning mechanism, and based on the hubbub I'm hearing from other people reading these right now, I know I'm not the only one who feels that way.

    I want to be notified about the tools offered by C++ for making things safer and more efficient, especially by avoiding dangerous legacy stuff. I don't want to know about someone's philosophical preferences, regardless of how awesome and correct they may be.

    Not everyone works in a production environment and not all code needs to be designed to rigorous production standards. If the tool is simply a nag then people are going to shut it off. Please use it for things that count.

    resolved 
    opened by khatharr 23
  • .at() and gsl::at() suggestion

    .at() and gsl::at() suggestion

    SL.con.3: Avoid bounds errors encourages the use of the .at() member function or the gsl::at() free function over the use of operator[]. However, this is quite inconvenient while working with nested structures. For example, here is a line from my Floyd-Warshall implementation:

    dist.at(i).at(j) = std::min(dist.at(i).at(j), dist.at(i).at(k) + dist.at(k).at(j));
    

    It would be nice to have a version of gsl::at which accepts a parameter pack of indices, like this: gsl::at(dist, i, j). This could make code using two or more dimensional arrays/vectors significantly less verbose and easier to read. Would you agree?

    opened by JaroPaska 0
  • C.12 should not apply to non-regular polymorphic types

    C.12 should not apply to non-regular polymorphic types

    Please consider limiting C.12 to data members of regular types. Alternatively, please amend the guideline to cover reasoning why it is damaging to other use cases, such as the one presented here. Thanks!

    I understand and support the reasoning for banning const data members in regular types. However, why ban it in a private data member of a non-copyable polymorphic type?

    I have read a few discussions about this issue, and I saw an argument made by @MikeGitb about this, but it was ignored.

    From the guideline:

    They are not useful

    For a private data member of a non-copyable polymorphic type, the const qualifier documents the intent they at least add a bit of "documentation". Example below.

    make types difficult to use by making them either uncopyable or partially uncopyable for subtle reasons

    The class is already non-copyable and is declared as such. The const qualifier on a private data member does not make it worse.

    It is very useful to me to mark some private data member as const to express and document how it is used. Since the type is non-copyable and non-assignable, there is no down side of marking it private, otherwise please amend the guideline with this case and reasoning.

    Example:

    class AnimatedMesh : public Renderable, public AnimatedObject { 
      public:
        explicit AnimatedMesh(shared_ptr<Renderer> renderer);
    
        // copy/assign marked as deleted
    
        void animate(...) override;
        void draw(...) override;
    
      private:
        const shared_ptr<Renderer> renderer;
        ...
        VBO vbo;
    };
    
    opened by strpbrk 0
  • Add exceptions to F.15, F.16, and F.18 for `shared_ptr` types

    Add exceptions to F.15, F.16, and F.18 for `shared_ptr` types

    Currently these guidelines conflict with R.34, R.35, and R.36.

    This conflict has led to confusion, where it's unclear which guidelines to prefer for shared_ptr types.

    In a previous PR I proposed preferring the "F" series of guidelines. This PR takes the opposite approach and prefers the "R" guidelines for shared_ptr types.

    I don't feel strongly about which guidelines to prefer, I just want to make sure the guidelines are internally consistent.

    opened by russellmcc 2
  • P.1: Express ideas directly in code  Example 4

    P.1: Express ideas directly in code Example 4

    This rule states that code should expresses its purpose by giving them correct naming as far as I understand. However in the example change_speed(double s); // bad: what does s signify? the lowercase s depicted here as a meaningles argument regarding its purpose on the other hand in the next example change_speed(Speed s); // better: the meaning of s is specified defining s argument here by specifiying its intent by defining as a purposeful type related with s seems to better approach . But the problem it is useless in the function scope again. So could it be a better way also declaring argument by its purpose like change_speed(double speed);

    opened by nzmgng 0
  • ES.43: Avoid expressions with undefined order of evaluation

    ES.43: Avoid expressions with undefined order of evaluation

    I understand that codes like

    v[i] = ++i;
    

    should be avoided at all costs and I'm not here to argue that. I just wanted to point out that the expression v[i] = ++i; is, at least as far as I'm aware, well-defined in C++11 and higher.

    opened by domdrag 5
Releases(v0.8)
All those who are willing to participate in the 7-day coding event Commit-Your-Code organized by GDSC, UIET have to fork this repository and contribute their solutions as per defined rules.

????‍?? Commit-Ur-Code ????‍?? GDSC UIET KUK ?? , welcomes you all to this amazing event where you will be introduced to the world of coding ?? . It i

Google Developer Student Club UIET KUK 9 Mar 24, 2022
Fast C++ container combining the best features of std::vector and std::deque

veque The double-ended vector A very fast C++17 container combining the best features of std::vector and std::deque "In Most Cases, Prefer Using deque

null 102 Nov 26, 2022
This repository aims to solve and create new problems from different spheres of coding. A path to help students to get access to solutions and discuss their doubts.

CPP-Questions-and-Solutions ?? This repository aims to solve and create new problems from different spheres of coding, which will serve as a single po

null 49 Oct 3, 2022
A series of important questions with solutions to crack the coding interview and ace it!

Data-Structures-Algorithms-Handbook Ace that coding interview! A series of important questions with solutions to crack the coding interview and ace it

Devangi Purkayastha 35 Dec 7, 2022
This repository is build for reviewing the CodingInterviews, Coding in ACM mode with C++.

CodingInterviews(剑指 Offer) 建立这个仓库为了重新复习一下《剑指 Offer》,上传的是ACM模式版本。 如果本仓库对你有任何帮助,请点 ?? 支持,谢谢! ??

Mike Zheng 17 Mar 4, 2022
A challenge to solve coding questions of top 6 companies in 30 days

A challenge to solve coding questions of top 6 companies in 30 days. An initiative started by Arsh Goyal. #RevisewithArsh #6Companies30Days

Hariket Sukeshkumar Sheth 13 Jun 29, 2022
Solutions for the Questions asked during Reverse Coding 2022.

Reverse Coding 2022 Solutions for the Questions asked during Reverse Coding 2022. This is the Open-Source release of the code used in Reverse Coding 2

ACM VIT 6 Aug 3, 2022
Minimal Linux Live (MLL) is a tiny educational Linux distribution, which is designed to be built from scratch by using a collection of automated shell scripts. Minimal Linux Live offers a core environment with just the Linux kernel, GNU C library, and Busybox userland utilities.

Minimal Linux Live (MLL) is a tiny educational Linux distribution, which is designed to be built from scratch by using a collection of automated shell scripts. Minimal Linux Live offers a core environment with just the Linux kernel, GNU C library, and Busybox userland utilities.

John Davidson 1.3k Jan 8, 2023
chap analyzes un-instrumented core files for leaks, memory growth, and corruption

chap analyzes un-instrumented ELF core files for leaks, memory growth, and corruption. It is sufficiently reliable that it can be used in automation t

VMware 307 Dec 21, 2022
HMS Core Scene Kit Slim Mesh Demo sample code demonstrates how to invoke external interfaces of SlimMesh to perform mesh simplification.

HMS Core Scene Kit Slim Mesh Demo English | 中文 Table of Contents Introduction Environments Requirements Result License Introduction The Slim Mesh is a

HMS 8 Jul 28, 2022
The Repository Contains the Set Way of Learning Cpplus With the help of programs And Notes.

Preface Since the C++ language varies so heavily between versions (e.g. C++0x, C++11, C++17, etc.), I will preface this cheat sheet by saying that the

Pawan Roshan Gupta 5 Oct 6, 2022
Background Music, a macOS audio utility: automatically pause your music, set individual apps' volumes and record system audio.

Background Music macOS audio utility Overview Auto-pause music Application volume Recording system audio Download Build and Install Uninstall Troubles

Kyle Neideck 12.8k Jan 2, 2023
L.A. Noire - V Patch | A community-made patch for the 2011's video game L.A Noire containing a set of fixes like an unlocked framerate or custom aspect ratios.

V-Patch for L.A Noire Complete Edition This project is not affiliated with Take-Two or Rockstar Games A while ago I wanted to replay L.A Noire on my n

null 193 Jan 2, 2023
This repository consists a set of problems that a beginner can starts with.

Beginner's Coding Sheet ?? ?? This Coding Sheet is provided by SIDDHARTH SINGH on his YouTube Channel. Here are the set of problems with its respectiv

Kishan Kumar Rai 5 Sep 30, 2022
Welcome to my dungeon. Here, I keep all my configuration files in case I have a stroke and lose all my memory. You're very welcome to explore and use anything in this repository. Have fun!

Fr1nge's Dotfiles Welcome to my dungeon. Here, I keep all my configuration files in case I have a stroke an d lose all my memory. You're very welcome

Fr1nge 33 Oct 28, 2022
This repository contains notes and starter code for Bit manipulation and mathematics session for DSA bootcamp organized by Codeflows.

Bitmanipulation_maths This repository contains notes and starter code for Bit manipulation and mathematics session for DSA bootcamp organized by Codef

Joe 7 Jun 15, 2022
cpp fundamentals and questions for beginners and intermediates

DSA 60 days Hi people! So we have started grasping dsa concepts and solving problems from 12 July. And we shall continue till September 10 Starting fr

Sushree Satarupa 211 Jan 5, 2023
A demonstration of implementing, and using, a "type safe", extensible, and lazy iterator interface in pure C99.

c-iterators A demonstration of implementing, and using, a "type safe", extensible, and lazy iterator interface in pure C99. The iterable is generic on

Chase 69 Jan 2, 2023
About Write a program to create a circular doubly linked list and perform insertions and deletions of various cases

Write a program to create a circular doubly linked list and perform insertions and deletions of various cases Circular Doubly Linked List Circular Dou

MH Miyazi 3 Aug 28, 2021