There was a discussion on GitHub regarding a programming style guide for arbalest. There is the HACKING in the brlcad repository, of course, but I don't think it is suited for modern C++ code. And, I hate especially the indentation rules.
The following represent very much what I used for the development of MOOSE, still they shall not be understood as a proposal for an arbalest style-guide. Rather, I want to demonstrate my expactations regarding a coding style guide. You may observe many issues among my set of rules. But I hope that they can serve as the starting point of a serious discussion.
The rules should be influenced by already existing ones, learn from their experience, but not copy them. Own classes, functions, etc. should be easily distingushable from alien code.
(For example, in MFC all class names start with "C". Therefore, somebody state the rule to do this in own code too. The result was that it became hard to distinguish own classes from MFC classes, e.g. in the debugger's call stack.)
The code should be compact, as long as it doesn't hinder its legibility.
There shall be no more than one statement per line.
Every source file begins with the copyright notice, license, and a short description.
Example:
/* V E C T O R L I S T. C P P
* BRL-CAD
*
* Copyright (c) 2020-2025 United States Government as represented by
* the U.S. Army Research Laboratory.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* version 2.1 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this file; see the file named COPYING for more
* information.
*/
/** @file VectorList.cpp
*
* BRL-CAD core C++ interface:
* vlist implementation
*/
Header files shall be protected against multiple including with a define of the form <NAMESPACE>_<FILENAME>_INCLUDED.
Example:
/* V E C T O R L I S T. H
* BRL-CAD
*
* Copyright (c) 2020-2025 United States Government as represented by
* the U.S. Army Research Laboratory.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* version 2.1 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this file; see the file named COPYING for more
* information.
*/
/** @file VectorList.h
*
* BRL-CAD core C++ interface:
* vlist declaration
*/
#ifndef BRLCAD_VECTORLIST_INCLUDED
#define BRLCAD_VECTORLIST_INCLUDED
[includes]
[forward declarations]
namespace BRLCAD {
[declarations]
}
#endif // BRLCAD_VECTORLIST_INCLUDED
Version information are stored in the version control system, and only there.
A single indent consists of 4 white-spaces.
Deeper indentations consist of a multiple of that.
Tabs may not be used for the source code layout.
Except for unary operators, there shall be at least one white-space before and after it.
Same operators shall be written below each other.
Example:
a = 7;
b = 6;
ab = 5;
cd += 4;
Unary operators are written without space between the operand.
Example:
++i;
Opening brackets shall be in the line preceding the block.
Example 1:
int FunctionName(void) {
Example 2:
for (size_t i = 0; i < 256; ++i) {
The content of a block has a single indent.
Example:
int FunctionName(void) {
int ret = 0;
return ret;
}
Closing brackets shall be in an own line.
Preceding a block, there shall be an empty line, except, the block follows immediately the beginning of another block.
Example 1:
int a = 7;
for (size_t i = 0; i < a; ++i) {
Example 2:
int FunctionName(void) {
for (size_t i = 0; i < 256; ++i) {
Following a block, there shall be an empty line, except, it follows immediately the end of another block or the block's preceding statement is continued.
Example 1:
int a = 7;
}
b = 6;
Example 2:
int a = 7;
}
}
Example 3:
if (a == 7) {
b = 6;
c = 5;
}
else
b = 0;
The parameters of a non-member function shall be written as a block. The opening bracket goes into an own line.
Example:
int FunctionName
(
int number,
double value
) {
This rule holds for declarations in header files as well as function implementations. This accentuates the impotence of the parameters of a function. They are easier to understand.
The parameters of class methods shall be written below each other, the first one in the same line as the function name.
Example:
class ClassName {
public:
int FunctionName(int number,
double value);
};
Often, classes have many methods with similar signature. A compact style eases the overview.
The declaration of a parameterless function shall be written in a single line.
Example:
int FunctionName(void) {
Keywords, which will handed over to the compiler, shall be written in camel-case.
Example:
int ExampleFunction(void) {
int exampleVariable = 7;
return exampleVariable;
}
Keywords, which are handled by the preprocessor, shall be written in capital letters.
Example:
#define MAX_USER_NUMBER 4
Function and type names start with a capital letter.
Variable names start with a lower letter.
Constants names start with a capital letter.
Variables, which are not declared in the function, where they are used, have an underline "_" in the name.
Variables, which are members of a class, start with "m_".
Example:
class ExampleClass {
public:
int& ExampleFunction(void) {
return m_exampleVariable;
}
private:
int m_exampleVariable;
};
A variable declaration shall be its initialization too, or a variable shall be declared not until a value can be assigned.
A convincing name shall be preferred to comments.
Bad:
size_t i = 0; // number of elements
Good:
size_t numberOfElements = 0;
This means more typing, but if somebody reads the code, e.g. hits this variable in a debugger, they see immediately what it is. No need to scroll back. The variable names are not for the compiler, it can handle "gt5jd7" as well, but for the programmers.
Functions have exactly one exit point (return statement).
This makes it easier to follow all processing paths, because they all end at the single exit point. In addition, it makes it easier to debug a function, because there is exactly one place for a break point at the function's end.
Example:
int Foo(
int* value
) {
int ret = 0;
if (value != nullptr)
ret = *value;
return ret;
}
goto statements are generally deprecated.
The usage of goto statements can be justified.
For example in exception handling:
bool OpenFile(
const char* fileName
) {
bool ret = false;
try {
if (!Exist(fileName))
throw 1;
if (!ReadingPermitted(fileName))
throw 1;
if (!FileHandleAvailable(fileName))
throw 1;
// open file
ret = true;
}
catch(int i) {}
return ret;
}
Here, the throw of an exception is used to jump out of the file processing. But, an exception isn't a simple jump but a much more complicated mechanism. In such a case, using goto statements can be a solution:
bool OpenFile(
const char* fileName
) {
bool ret = false;
if (!Exist(fileName))
goto EXIT_LABEL;
if (!ReadingPermitted(fileName))
goto EXIT_LABEL;
if (!FileHandleAvailable(fileName))
goto EXIT_LABEL;
// open file
ret = true;
EXIT_LABEL:
return ret;
}
See also recommendation 2 in section 14.11 of Bjarne Stroustrup's "The C++ Programming Language".
adapting an existing style that something like astyle or vs code natively supports might be best
I'm not sure what you have in mind. It should be feasible by humans with an ordinary editor to follow the rules. E.g., I use Notepad++ or Kate. But with these, it's very hard to do the indentation in brlcad right. If a special software is necessary to do follow a rule, it would be a red flag for me.
Current indentation style in BRL-CAD is a legacy exception, and I think we all agree'd long ago to abandon it. Just a matter of timing to flip the style switch as it will invalidate all outstanding patches and pull requests...
I'd hope we (as a team) could spend a month or two integrating and closing out as many as possible before doing a wholesale style change.
I actually see no major issues myself with the style guide and examples above (for arbalest or otherwise). Very much a C++ style I think as some constructs don't extend well to C-only code. Only thing that even jumped out was perhaps preferring a more concise preprocessor header inclusion protections, starting everything in uppercase, and not really liking parameter blocks unless we're documenting them right there. I generally want as many lines of code to fit on my screen as possible so long as it doesn't violate one-thing-per line (with params not being a thing, the decl is the thing). Towards that end, the orphaned else is another oddity that just adds lines imho, but I could probably get used to it.
if it weren't for that, what's described is highly similar to the K&R one true brace style (1TBS) and Qt/KDE style guide (though you disagree more there on some points).
Here's the built-in styles supported by clang-format and astyle respectively:
LLVM
(the default), Google
, Chromium
, Mozilla
, WebKit
, Microsoft
, GNU
allman / bsd / break
, java / attach
, kr / k&r / k/r
, stroustrup
, whitesmith
, vtk
, ratliff / banner
, gnu
, linux / knf
, horstmann / run‑in
, 1tbs / otbs
, google
, mozilla
, webkit
, pico
, lisp
What you described, aside from the three things that jumped out to me (as nobody does those afaikt), is very similar to the WebKit style (except opening brace) and LLVM style (except indent).
...according to my first "basic principle".
The second says: "The code should be compact, as long as it doesn't hinder its legibility." An important use case is the fast scrolling through a source file. The beginning of functions are emphasized, including their parameter lists, because that's the most important information about functions. This is, what e.g. doxygen extracts for documentation. It shall be recognizable by scrolling by. Some of the other rules shall support the fast scrolling too.
Last updated: Aug 07 2025 at 01:01 UTC