-
Notifications
You must be signed in to change notification settings - Fork 1.4k
Document current coding style guidelines. #2298
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
1366385
5922dd4
7fae453
9cc9105
31ec4ab
ea2bfbd
818f111
a8a6b89
68471fc
89aafac
9d7e799
3c9c6cb
c97efc0
0d1fbce
79b51a9
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -0,0 +1,83 @@ | ||||||
/// \file RCodingStyle.cxx | ||||||
/// \author Axel Naumann <axel@cern.ch> | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. how does this look for multiple authors? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should be addressed. |
||||||
/// \date 2018-07-24 | ||||||
// The above entries are mostly for giving some context. | ||||||
// The "author" field gives a hint whom to contact in case of questions, also | ||||||
// from within the team. The date shows whether this is ancient or only part | ||||||
// of the latest release. It's the date of creation / last massive rewrite. | ||||||
|
||||||
/************************************************************************* | ||||||
* Copyright (C) 1995-2018, Rene Brun and Fons Rademakers. * | ||||||
* All rights reserved. * | ||||||
* * | ||||||
* For the licensing terms see $ROOTSYS/LICENSE. * | ||||||
* For the list of contributors see $ROOTSYS/README/CREDITS. * | ||||||
*************************************************************************/ | ||||||
|
||||||
// This file demonstrates the coding style to be used for new ROOT files. | ||||||
// For much of the rationale see Scott Meyer's "Efficient Modern C++" and the | ||||||
// [C++ core guidelines](https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md), | ||||||
// plus a fairly large portion of "coding style personality" inherited from 20 years | ||||||
// of ROOT: there is nothing wrong with them; they make ROOT classes easily | ||||||
// recognizable. Our users are used to it. No need to change. | ||||||
|
||||||
// First, include the header belonging to the source file | ||||||
#include "RCodingStyle.hxx" | ||||||
|
||||||
// Now the same order as for the header: | ||||||
// ROOT headers in alphabetical order; all new ROOT headers are under `ROOT/` | ||||||
#include "ROOT/RAxis.hxx" | ||||||
|
||||||
// Old ones are found in include/ without prefix. | ||||||
// New headers should reduce the use of "old" ROOT headers, and instead use | ||||||
// stdlib headers and new-style headers wherever possible. | ||||||
#include "TROOT.h" // for TROOT::GetVersion() | ||||||
|
||||||
// Then standard library headers, in alphabetical order. | ||||||
#include <vector> | ||||||
|
||||||
// Include non-ROOT, non-stdlib headers last. | ||||||
// Rationale: non-ROOT, non-stdlib headers often #define like mad. Reduce interference | ||||||
// with ROOT or stdlib headers. | ||||||
#ifdef R__LINUX | ||||||
// Indent nested preprocessor defines, keeping '#' on column 1: | ||||||
#include <dlfcn.h> | ||||||
#endif | ||||||
|
||||||
// Do not use `namespace ROOT {` in sources; do not rely on `using namespace ROOT` for | ||||||
// finding the implemented overload. This causes ambiguities if the header and the source | ||||||
// disagree on the parameters of free functions, e.g. | ||||||
// ``` | ||||||
// namespace ROOT { | ||||||
// double Add(const RExampleClass& a, const RExampleClass& b, int i) { return 17.; } | ||||||
// } | ||||||
// ``` | ||||||
// will just compile (despite the wrong `int` argument), while | ||||||
// ``` | ||||||
// double ROOT::Add(const RExampleClass& a, const RExampleClass& b, int i) { return 17.; } | ||||||
// ``` | ||||||
// will not. | ||||||
|
||||||
// Unused parameters are commented out; they often carry useful semantical info. | ||||||
// We use the same parameter names in headers and sources. | ||||||
double ROOT::Add(const RExampleClass & /*a*/, const RExampleClass & /*b*/) | ||||||
{ | ||||||
return 17.; | ||||||
} | ||||||
|
||||||
// Pins the vtable. | ||||||
ROOT::RExampleClass::~RExampleClass() | ||||||
{ | ||||||
} | ||||||
Comment on lines
+69
to
+71
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why not |
||||||
|
||||||
/// Instead of static data members (whether private or public), use outlined static | ||||||
/// functions. This solves the static initializion fiasco, and delays the initialization | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. initializion There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
/// to first use. | ||||||
const std::string &ROOT::RExampleClass::AccessStaticVar() | ||||||
{ | ||||||
// NOTE that this initialization is thread-safe! | ||||||
static std::string sString = gROOT->GetVersion(); | ||||||
return sString; | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What about There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. a) that's not the point of this demo-function, and b) that won't give you a There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I have improved the code, I hope it's less confusing now? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, but maybe |
||||||
} | ||||||
|
||||||
// End the file with a trailing newline. |
Original file line number | Diff line number | Diff line change | ||||||||
---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,251 @@ | ||||||||||
/// \file RCodingStyle.hxx | ||||||||||
/// \author Axel Naumann <axel@cern.ch> | ||||||||||
/// \author Other Author <other@author> | ||||||||||
/// \date 2018-07-24 or \date July, 2018 | ||||||||||
// The above entries are mostly for giving some context. | ||||||||||
// The "author" field gives a hint whom to contact in case of questions, also | ||||||||||
// from within the team. The date shows whether this is ancient or only part | ||||||||||
// of the latest release. It's the date of creation / last massive rewrite. | ||||||||||
|
||||||||||
/************************************************************************* | ||||||||||
* Copyright (C) 1995-2018, Rene Brun and Fons Rademakers. * | ||||||||||
* All rights reserved. * | ||||||||||
* * | ||||||||||
* For the licensing terms see $ROOTSYS/LICENSE. * | ||||||||||
* For the list of contributors see $ROOTSYS/README/CREDITS. * | ||||||||||
*************************************************************************/ | ||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do we need this header on every file? The top 3 lines are obsolete almost immediately, and git is there for that, while the copyright can be in a file at top level stating that that's the copyright unless a different one exists in the file. Also, many files don't have the header in any case:
and many others are out of date:
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There is a difference between touching a file and writing it. I have argued before that this is a nice way of leaving traces also for people with limited participation in ROOT, and it's a good way of knowing whom to contact / ownership.
Multiple opinions exist on that one.
Indeed we have many files that have a different (c). There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
I still think that |
||||||||||
|
||||||||||
// This file demonstrates the coding styles to be used for new ROOT files. | ||||||||||
// See the accompanying source file for context. | ||||||||||
|
||||||||||
// File names correspond to the name of the main class that they contain. | ||||||||||
// Our users will expect that a file called "RCodingStyle.hxx" contains a class | ||||||||||
// named `RCodingStyle`. | ||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I totally agree with this, my comment is that there are/will be exceptions: see e.g. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. These are not "follow or die" rules. You simply need to have good reasons for violating this. |
||||||||||
|
||||||||||
// All files start with a Doxygen header, followed by the copyright statement. | ||||||||||
// The "-year" part is kept up to date by a script. | ||||||||||
|
||||||||||
// The file must contain no trailing whitespace including no indentation-only lines. | ||||||||||
// Except for extreme cases, line breaks should happen between 80 and 120 characters. | ||||||||||
|
||||||||||
// The first non-comment, non-empty line must be the #include guard. | ||||||||||
// Acceptable forms are: | ||||||||||
// ROOT_RCodingStyle, ROOT_RCodingStyle_hxx, ROOT_RCodingStyle_Hxx, | ||||||||||
// ROOT_RCODINGSTYLE, ROOT_RCODINGSTYLE_HXX | ||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why not choose one only? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What or whom could a difference here confuse? What's the advantage of choosing one? They should be file-local, I sort of like that nobody can rely on them outside this file ;-) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We should likely mangle at least the component path in include protector. It may become very ugly to debug if the include protector names are duplicate between two unrelated files. I'd make sense to me to stick with one include protector style (the latter). There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Choosing only one is good for consistency. Isn't this trying to improve exactly that? I don't really care which one we choose, as long as it's consistent throughout the code. At the very least one choice should be recommended over the others. There's also |
||||||||||
// The first is preferred. | ||||||||||
#ifndef ROOT_RCodingStyle | ||||||||||
|
||||||||||
// Especially within header files, using forward declarations instead of | ||||||||||
// including the relevant headers wherever possible. | ||||||||||
// EXCEPTION: standard library classes must be #included, not forward declared. | ||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Even the easy-to-forward-declare ones? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Like? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Doh, I get your point :) |
||||||||||
// All files must be stand-alone: all types must be available through a | ||||||||||
// forward declaration or an #include; it is not acceptable to rely on an | ||||||||||
// included header to itself include another header needed by the file. | ||||||||||
|
||||||||||
// Include ROOT's headers first, in alphabetical order: | ||||||||||
// Rationale: make sure that ROOT headers are standalone. | ||||||||||
// Do not use #include guards at the point of `#include`. | ||||||||||
// Rationale: compilers optimize this themselves, this is interfering with their optimization. | ||||||||||
// Use <>, not "". | ||||||||||
// Rationale: "" looks at ./ first; as ROOT headers are included by user code | ||||||||||
// that adds context fragility. | ||||||||||
#include <ROOT/TSeq.hxx> | ||||||||||
// Include v6 ROOT headers last. | ||||||||||
// You're welcome to state what's used from a header, i.e. why it's included. | ||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In practice, this might be outdated the second time a file is touched. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fully agree! |
||||||||||
#include <Rtypes.h> // for ULong64_t | ||||||||||
|
||||||||||
// Now include other C++ headers hat are not from the stdlib: | ||||||||||
// e.g. #include <cppyy/CPpYy.h> | ||||||||||
|
||||||||||
// Include stdlib headers next, in alphabetical order. | ||||||||||
#include <string> | ||||||||||
|
||||||||||
// Include C headers last. | ||||||||||
// Rationale: non-ROOT, non-stdlib headers often #define like mad. Reduce interference | ||||||||||
// with ROOT or stdlib headers. | ||||||||||
#include <curses.h> | ||||||||||
Comment on lines
+45
to
+66
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It would be great if these rules could be automated via the |
||||||||||
|
||||||||||
// Say NO to | ||||||||||
// - `using namespace` in at global scope in headers | ||||||||||
// - variables, types, functions etc at global scope | ||||||||||
// - preprocessor `#define`s except for #include guards (and are cases where | ||||||||||
// `#include`d headers require them) | ||||||||||
|
||||||||||
namespace ROOT { | ||||||||||
// All new classes are within the namespace ROOT. | ||||||||||
|
||||||||||
// Forward declare before class definitions. | ||||||||||
namespace Experimental { | ||||||||||
class RAxisConfig; | ||||||||||
} | ||||||||||
|
||||||||||
///\class RExampleClass | ||||||||||
/// Classes and structs start with 'R'. And they are documented. | ||||||||||
class RExampleClass { | ||||||||||
public: | ||||||||||
// FIRST section: public types. | ||||||||||
|
||||||||||
/// Nested types are documented, too. Do not use `typedef` but `using`. | ||||||||||
/// Type aliases end with "_t". | ||||||||||
using SeqULL_t = TSeq<ULong64_t>; | ||||||||||
|
||||||||||
///\class Nested | ||||||||||
/// This is a nested class. Only use `struct`s for simple aggregates without | ||||||||||
/// methods and all public members. | ||||||||||
struct Nested { | ||||||||||
std::string fNestedName; ///< The nested name. | ||||||||||
}; | ||||||||||
|
||||||||||
private: | ||||||||||
// SECOND section: private types. | ||||||||||
|
||||||||||
// Any type used by any public / protected interface must also be public / protected! | ||||||||||
// This is not enforced by C++ but required by this coding style. | ||||||||||
using Nesteds_t = std::vector<Nested>; | ||||||||||
|
||||||||||
// THIRD section: data members. | ||||||||||
|
||||||||||
// Data member names start with `f`. | ||||||||||
// Documentation comments can be in front of data members or right behind them, see below. | ||||||||||
// For the latter case, comments must be column-aligned: | ||||||||||
|
||||||||||
int fIntMember = -2; ///< Use inline initialization at least for fundamental types. | ||||||||||
std::vector<Nested> fManyStrings; ///<! This marks a member that does not get serialized (I/O comment). | ||||||||||
static constexpr const int kSeq = -7; ///< A static constexpr (const) variable starts with `k`. | ||||||||||
|
||||||||||
/// Don't explicitly default initialize (`{}`) | ||||||||||
std::vector<ROOT::Experimental::RAxisConfig> fAxes; //! For pre-comment cases, ROOT I/O directives go here. | ||||||||||
|
||||||||||
/// A static variable starts with `fg`. Avoid all non-constexpr static variables! Long data | ||||||||||
/// member documentation is just fine, but then put it in front of the data member. | ||||||||||
static std::string fgNameBadPleaseUseStaticFunctionStaticVariable; | ||||||||||
|
||||||||||
protected: | ||||||||||
/// FOURTH section: non-public functions. | ||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There seems to be no THIRD. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||||||||||
|
||||||||||
/// Instead of static data members (whether private or public), use outlined static | ||||||||||
/// functions. See the implementation in the source file. | ||||||||||
static const std::string &AccessStaticVar(); | ||||||||||
|
||||||||||
public: | ||||||||||
// FIFTH section: methods, starting with constructors, then alphabetical order, possibly | ||||||||||
// grouped by functionality (\ingroup or \{ \}). | ||||||||||
|
||||||||||
/// Use `= default` inside the class whenever possible | ||||||||||
RExampleClass() = default; | ||||||||||
|
||||||||||
/// Classes with virtual functions must have a virtual destructor. If all other functions are | ||||||||||
/// pure virtual or inlined, the destructor should be outlined to pin the class's vtable to an | ||||||||||
/// object file. I.e. say `= default` in the source, not here. | ||||||||||
virtual ~RExampleClass(); | ||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this is not pinned in the source file, it would be nice to add it. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should be addressed. |
||||||||||
|
||||||||||
/// For trivial functions, use `const` and possibly `constexpr`, but not `noexcept`. | ||||||||||
int GetAsInt() const { return fIntMember; } | ||||||||||
|
||||||||||
/// Static functions line up alphabetically with the others. | ||||||||||
static int GetSeq() { return kSeq; } | ||||||||||
|
||||||||||
/// It is fine to have one-line function declarations. | ||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I guess you mean function definitions. |
||||||||||
void SetInt(int i) { fIntMember = i; } | ||||||||||
|
||||||||||
/// \brief Replace the many strings | ||||||||||
/// \param[in] input A collection of strings to use. | ||||||||||
/// \return Always return true but if it could fail would return false in that case. | ||||||||||
/// | ||||||||||
/// All functions must have at least one line of comments, parseable/useable by doxygen. | ||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That sounds very strict to me. Simple functions with good names should not need comments. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I agree and disagree. One line of comment should be mandatory, because otherwise the docs look like this: This one line should be one sentence, ending with a I agree, though, that after having written a single sentence, you may leave out the rest for trivial functions. |
||||||||||
bool SetManyStrings(const std::vector<Nested>& input) { fManyStrings = input; return true; } | ||||||||||
|
||||||||||
/// Virtual functions are still fine (though we try to avoid them as they come with a call | ||||||||||
/// and optimization penalty). See `RCodingStyle` for overriding virtual functions. | ||||||||||
virtual void VirtualFunction() = 0; | ||||||||||
}; | ||||||||||
|
||||||||||
///\class RCodingStyle | ||||||||||
/// This is exhaustive documentation of the class template, explaining the constraints | ||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The first thing after the \class macro should be the brief documentation. Doxygen takes the first sentence of the docs if no |
||||||||||
/// on the template parameters, e.g. | ||||||||||
/// `IDX` must be positive, `T` must be copyable. | ||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Recommend using doxygen's
Suggested change
|
||||||||||
/// Disabled if `T` is of reference type. | ||||||||||
template <int IDX, // Template parameters are all-capital letters | ||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this is the only new convention that I don't like, it makes template-heavy code a bit heavy to look at (just go to There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It helps to identify template parameters as such. I often use a using declaration to "convert" the template param to a type (with type-spelling). But I see your point. Let's discuss at a team meeting! |
||||||||||
class T, // Use `typename` for T being a builtin (int, float,...) else `class`. | ||||||||||
// template parameter name `T` is fine for generic class names | ||||||||||
// we use `enable_if` through unnamed template parameters and provide a `assert`-style message | ||||||||||
// to make the diagnostics more understandable. | ||||||||||
class = std::enable_if<"Must only be used with non-reference types" && !std::is_reference<T>::value>> | ||||||||||
class RCodingStyle : public RExampleClass { | ||||||||||
private: | ||||||||||
T fMember; ///< The wrapped value. | ||||||||||
|
||||||||||
public: | ||||||||||
// Use static_assert excessively: it makes diagnostics much more readable, | ||||||||||
// and helps readers of your code. | ||||||||||
static_assert(IDX > 0, "IDX must be >0."); | ||||||||||
|
||||||||||
/// Defaulted default constructor. | ||||||||||
RCodingStyle() = default; | ||||||||||
|
||||||||||
// Open a group: | ||||||||||
/// \{ \name copy pperations | ||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||
|
||||||||||
// Use `= delete` instead of private, unimplemented. | ||||||||||
// To avoid copy and move construction and assignment, `delete` the copy | ||||||||||
// constructor and copy-assignment operator, see https://stackoverflow.com/a/15181645/6182509 | ||||||||||
RCodingStyle(const RCodingStyle &) = delete; | ||||||||||
RCodingStyle &operator=(const RCodingStyle &) = delete; | ||||||||||
/// \} | ||||||||||
|
||||||||||
/// Virtual destructors of derived classes may be decorated with `virtual` (even though | ||||||||||
/// they "inherit" the virtuality of the virtual base class destructor). | ||||||||||
virtual ~RCodingStyle() {} | ||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should probably be |
||||||||||
|
||||||||||
/// Overridden virtual functions do not specify `virtual` but either `override` or `final`. | ||||||||||
void VirtualFunction() override {} | ||||||||||
|
||||||||||
/// "Free" (i.e. non-class member) operators should be declared as "hidden friends". | ||||||||||
/// This makes them available only when needed, instead of adding to the long list of | ||||||||||
/// "no matching overload for a+b, did you mean ...(hundreds of unrelated types)..." | ||||||||||
friend RCodingStyle operator+(const RCodingStyle &a, const RCodingStyle &b) | ||||||||||
{ | ||||||||||
RCodingStyle ret{a}; | ||||||||||
ret.SetInt(ret.GetAsInt() + b.GetAsInt()); | ||||||||||
return ret; | ||||||||||
} | ||||||||||
|
||||||||||
/// Heterogenous operators should be implemented as hidden-friend functions: | ||||||||||
friend RCodingStyle operator+(const RCodingStyle &a, int i) | ||||||||||
{ | ||||||||||
RCodingStyle ret{a}; | ||||||||||
ret.SetInt(ret.GetAsInt() + i); | ||||||||||
return ret; | ||||||||||
} | ||||||||||
|
||||||||||
/// ...as the symmetrical / inverse version can only be specified as non-member: | ||||||||||
friend RCodingStyle operator+(int i, const RCodingStyle &a) { return a + i; } | ||||||||||
}; | ||||||||||
|
||||||||||
/// Functions that access only public members of ROOT classes shall be in here. | ||||||||||
/// \param a - first RExampleClass to add. | ||||||||||
/// \param b - second RExampleClass to add. | ||||||||||
Comment on lines
+226
to
+227
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think that doxygen generates better docs without the
Suggested change
|
||||||||||
double Add(const RExampleClass &a, const RExampleClass &b); | ||||||||||
|
||||||||||
// Rules on sub-namespaces. | ||||||||||
// All namespaces are CamelCase, i.e. starting with an upper case character. | ||||||||||
namespace CodingStyle { | ||||||||||
// Parts of ROOT might want to use sub-namespaces for *internal* code. | ||||||||||
// Such code might include the following two namespaces: | ||||||||||
namespace Detail { | ||||||||||
// Contains code that is not expected to be seen by the everage user. | ||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. typo There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||
// It might provide customization points for advanced users, or | ||||||||||
// interfaces that are useful for performance-critical code, at the | ||||||||||
// expense of robustness. | ||||||||||
} | ||||||||||
|
||||||||||
namespace Internal { | ||||||||||
// Contains code that is meant to be used only by ROOT itself. We do not guarantee | ||||||||||
// interface stability for any type inside any sub-namespace of `ROOT::` called | ||||||||||
// `Internal`, i.e. `ROOT::Internal` or `ROOT::...::Internal`. | ||||||||||
} | ||||||||||
} | ||||||||||
|
||||||||||
} // namespace ROOT | ||||||||||
#endif // ROOT_RCodingStyle | ||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Commenting on the commit message... Maybe a |
||||||||||
// The file must end on a trailing new-line. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sometimes it makes sense to add
\brief
section which describes the contents and the purpose of the files.