2018-04-14 11:03:19 +00:00
|
|
|
|
# Coding Style
|
2014-02-27 15:57:22 +00:00
|
|
|
|
|
2018-04-10 07:08:46 +00:00
|
|
|
|
Here are some of the basics that we are trying to enforce for our coding style
|
|
|
|
|
and conventions. The existing code (as of the commit that adds these lines) is
|
|
|
|
|
not yet fully consistent to these rules, but following these rules will make
|
2014-02-27 15:57:22 +00:00
|
|
|
|
sure that no one yells at you about your patches.
|
|
|
|
|
|
|
|
|
|
We have a script that can be used to reformat code to be reasonably close
|
2023-03-26 16:24:54 +00:00
|
|
|
|
to these rules; it's in `scripts/whitespace.pl` – this script requires
|
2014-02-27 15:57:22 +00:00
|
|
|
|
clang-format to be installed (which sadly isn't installed by default on
|
|
|
|
|
any of our platforms; even on Mac where clang is the default compiler).
|
|
|
|
|
|
2023-03-26 16:24:54 +00:00
|
|
|
|
At the end of this file are some ideas for your `.emacs` file (if that's
|
2014-02-27 15:57:22 +00:00
|
|
|
|
your editor of choice) as well as for QtCreator. If you have settings for
|
|
|
|
|
other editors that implement this coding style, please add them here.
|
|
|
|
|
|
2024-09-06 20:16:28 +00:00
|
|
|
|
## Basic style rules
|
2014-02-27 15:57:22 +00:00
|
|
|
|
|
2018-04-14 11:03:19 +00:00
|
|
|
|
* all indentation is tabs (set to 8 char) with the exception of
|
2018-04-09 05:59:33 +00:00
|
|
|
|
continuation lines that are aligned with tabs and then spaces
|
2014-01-16 04:50:56 +00:00
|
|
|
|
|
2018-04-14 11:03:19 +00:00
|
|
|
|
* all keywords followed by a '(' have a space in between
|
2018-07-26 12:01:16 +00:00
|
|
|
|
```
|
2023-03-26 16:12:43 +00:00
|
|
|
|
if (condition)
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < 5; i++)
|
2018-07-26 12:01:16 +00:00
|
|
|
|
```
|
2014-01-16 04:50:56 +00:00
|
|
|
|
|
2018-04-14 11:03:19 +00:00
|
|
|
|
* function calls do NOT have a space between their name and argument
|
2018-07-26 12:01:16 +00:00
|
|
|
|
```
|
2023-03-26 16:12:43 +00:00
|
|
|
|
i = some_function(argument);
|
2018-07-26 12:01:16 +00:00
|
|
|
|
```
|
2014-01-16 04:50:56 +00:00
|
|
|
|
|
2018-04-14 11:03:19 +00:00
|
|
|
|
* usually there is no space on the inside of parenthesis (see examples
|
2014-01-16 04:50:56 +00:00
|
|
|
|
above)
|
|
|
|
|
|
2018-04-14 11:03:19 +00:00
|
|
|
|
* function / method implementations have their opening curly braces in
|
2014-01-16 04:50:56 +00:00
|
|
|
|
column 1
|
|
|
|
|
|
2018-04-14 11:03:19 +00:00
|
|
|
|
* all other opening curly braces follow at the end of the line, with a
|
2014-01-16 04:50:56 +00:00
|
|
|
|
space separating them:
|
2018-07-26 12:01:16 +00:00
|
|
|
|
```
|
2023-03-26 16:12:43 +00:00
|
|
|
|
if (condition) {
|
|
|
|
|
dosomething();
|
|
|
|
|
dosomethingelse();
|
|
|
|
|
}
|
2018-07-26 12:01:16 +00:00
|
|
|
|
```
|
2014-01-16 04:50:56 +00:00
|
|
|
|
|
2023-03-26 16:24:54 +00:00
|
|
|
|
* both sides of an `if` / `else` clause either use or do not use curly braces:
|
2018-07-26 12:01:16 +00:00
|
|
|
|
```
|
2023-03-26 16:12:43 +00:00
|
|
|
|
if (condition)
|
|
|
|
|
i = 4;
|
|
|
|
|
else
|
|
|
|
|
j = 6;
|
|
|
|
|
|
|
|
|
|
if (condition) {
|
|
|
|
|
i = 6;
|
|
|
|
|
} else {
|
|
|
|
|
i = 4;
|
|
|
|
|
j = 6;
|
|
|
|
|
}
|
2018-07-26 12:01:16 +00:00
|
|
|
|
```
|
2014-01-16 04:50:56 +00:00
|
|
|
|
|
2018-04-14 11:03:19 +00:00
|
|
|
|
* use space to make visual separation easier
|
2018-07-26 12:01:16 +00:00
|
|
|
|
```
|
2023-03-26 16:12:43 +00:00
|
|
|
|
a = b + 3 + e / 4;
|
2018-07-26 12:01:16 +00:00
|
|
|
|
```
|
2014-01-16 04:50:56 +00:00
|
|
|
|
|
2018-04-14 11:03:19 +00:00
|
|
|
|
* continuation lines have the operator / comma at the end
|
2018-07-26 12:01:16 +00:00
|
|
|
|
```
|
2023-03-26 16:12:43 +00:00
|
|
|
|
if (very_long_condition_1 ||
|
|
|
|
|
condition_2)
|
|
|
|
|
|
|
|
|
|
b = a + (c + d +
|
|
|
|
|
f + z);
|
2018-07-26 12:01:16 +00:00
|
|
|
|
```
|
2014-01-16 04:50:56 +00:00
|
|
|
|
|
2018-04-14 11:03:19 +00:00
|
|
|
|
* in a C++ constructor initialization list, the colon is on the same line and
|
2014-01-22 16:25:14 +00:00
|
|
|
|
continuation lines are aligned as the rule above:
|
2018-07-26 12:01:16 +00:00
|
|
|
|
```
|
2023-03-26 16:12:43 +00:00
|
|
|
|
ClassName::ClassName() : x(1),
|
|
|
|
|
y(2),
|
|
|
|
|
z(3)
|
|
|
|
|
{
|
|
|
|
|
}
|
2018-07-26 12:01:16 +00:00
|
|
|
|
```
|
2014-01-22 16:25:14 +00:00
|
|
|
|
|
2018-04-14 11:03:19 +00:00
|
|
|
|
* unfortunate inconsistency
|
2023-03-26 16:18:58 +00:00
|
|
|
|
|
2024-09-06 20:16:28 +00:00
|
|
|
|
- Core code usually uses underscores to structure names
|
2020-02-03 18:12:50 +00:00
|
|
|
|
```
|
2024-09-06 20:16:28 +00:00
|
|
|
|
variable_or_class_in_core
|
2020-02-03 18:12:50 +00:00
|
|
|
|
```
|
2024-09-06 20:16:28 +00:00
|
|
|
|
- In contrast, Qt / display layer code usually uses camelCase
|
2020-02-03 18:12:50 +00:00
|
|
|
|
```
|
2024-09-06 20:16:28 +00:00
|
|
|
|
variableInQt
|
2020-02-03 18:12:50 +00:00
|
|
|
|
```
|
|
|
|
|
for variable names and PascalCase
|
|
|
|
|
```
|
2024-09-06 20:16:28 +00:00
|
|
|
|
ClassInQt
|
2020-02-03 18:12:50 +00:00
|
|
|
|
```
|
|
|
|
|
for names of classes and other types
|
2014-01-16 04:50:56 +00:00
|
|
|
|
|
|
|
|
|
where the two meet, use your best judgment and go for best consistency
|
2020-02-03 18:12:50 +00:00
|
|
|
|
(i.e., where does the name "originate")
|
2014-01-16 05:58:06 +00:00
|
|
|
|
|
2022-03-27 22:16:59 +00:00
|
|
|
|
* macro names should be capitalized; e.g., prefer
|
|
|
|
|
```
|
|
|
|
|
#define FROB 17
|
|
|
|
|
#define FROBULATE(x) (x)+FROB
|
|
|
|
|
```
|
|
|
|
|
to
|
|
|
|
|
```
|
|
|
|
|
#define frob 17
|
|
|
|
|
#define frobulate(x) (x)+frob
|
|
|
|
|
```
|
|
|
|
|
|
2024-09-06 20:16:28 +00:00
|
|
|
|
Since C++ is strongly typed, avoid macros where possible.
|
|
|
|
|
For constants use `constexpr`:
|
|
|
|
|
```
|
|
|
|
|
static constexpr int frob = 17;
|
|
|
|
|
```
|
|
|
|
|
and for functions use templated inline functions such as
|
|
|
|
|
```
|
|
|
|
|
template<typename T>
|
|
|
|
|
static bool less_than(T x, T y)
|
|
|
|
|
{
|
|
|
|
|
return x < y;
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
2019-12-23 19:26:19 +00:00
|
|
|
|
* there is a strong preference for lower case file names; sometimes conventions
|
|
|
|
|
or outside requirements make camelCase filenames the better (or only) choice,
|
|
|
|
|
but absent such an outside reason all file names should be lower case
|
2019-12-25 09:32:07 +00:00
|
|
|
|
This rule applies to new file names, existing file names should not be
|
|
|
|
|
changed without a reason.
|
2019-12-23 19:26:19 +00:00
|
|
|
|
|
2019-12-25 09:30:11 +00:00
|
|
|
|
* cpp/h file names should usually be identical to the class name but in lower
|
|
|
|
|
case. Where it seems appropriate, multiple, closely related classes can be
|
|
|
|
|
in a single file with a more generic name.
|
|
|
|
|
|
2023-03-26 16:24:54 +00:00
|
|
|
|
* `switch` statements with blocks are a little bit special (to avoid indenting
|
2014-01-16 05:58:06 +00:00
|
|
|
|
too far)
|
2018-07-26 12:01:16 +00:00
|
|
|
|
```
|
2023-03-26 16:12:43 +00:00
|
|
|
|
switch (foo) {
|
|
|
|
|
case FIRST:
|
|
|
|
|
whatever();
|
|
|
|
|
break;
|
|
|
|
|
case SECOND: {
|
|
|
|
|
int i;
|
|
|
|
|
for (i = 0; i < 5; i++)
|
|
|
|
|
do_something(i);
|
|
|
|
|
}
|
|
|
|
|
}
|
2018-07-26 12:01:16 +00:00
|
|
|
|
```
|
2014-02-27 15:57:22 +00:00
|
|
|
|
|
2024-09-06 20:16:28 +00:00
|
|
|
|
## Separation of core and UI layer and historical remarks
|
|
|
|
|
|
|
|
|
|
Ideally, we strive for a separation of core functionality and UI layer.
|
|
|
|
|
In practice however, the distinction is rather fuzzy and the code base is
|
|
|
|
|
inconsistent. The current state is due to the fact that the project was
|
|
|
|
|
originally written in C with the gtk library. Later, the UI layer was
|
|
|
|
|
converted to Qt, whereas the core functionality was still C. Gradually
|
|
|
|
|
more and more Qt and C++ creeped into the core layer. Recently we
|
|
|
|
|
switched to full C++.
|
|
|
|
|
|
|
|
|
|
To keep the option of non-Qt frontends, we should strive to use as few Qt
|
|
|
|
|
primitives in the core code as possible. However, some parts
|
|
|
|
|
are deeply interwoven with Qt, such as for example the translation machinery.
|
|
|
|
|
Moreover, some platform independent features, such as regexps or URL handling
|
|
|
|
|
might be hard to replace.
|
|
|
|
|
|
|
|
|
|
## C++
|
|
|
|
|
|
|
|
|
|
Since the project was originally written in C, some of the creators and
|
|
|
|
|
original contributors may feel overwhelmed by all too
|
|
|
|
|
"modern" C++, so try to avoid "fancy" constructs such as template meta
|
|
|
|
|
programming, unless they make the code distinctly simpler.
|
|
|
|
|
|
|
|
|
|
Also many of the (potential) contributors will not have an extensive
|
|
|
|
|
background in C++, so strive for simplicity.
|
|
|
|
|
|
2018-04-14 11:03:19 +00:00
|
|
|
|
## Coding conventions
|
2018-04-10 07:08:46 +00:00
|
|
|
|
|
2018-04-14 11:03:19 +00:00
|
|
|
|
* variable declarations
|
2023-03-26 16:18:58 +00:00
|
|
|
|
|
2024-09-06 20:16:28 +00:00
|
|
|
|
In C++ the lifetime of a variable often coincides with the
|
2018-07-26 12:01:16 +00:00
|
|
|
|
lifetime of a resource (e.g. file) and therefore the variable is defined
|
2024-09-06 20:16:28 +00:00
|
|
|
|
at the place where the resource is acquired. The resource is freed,
|
|
|
|
|
when the variable goes out of scope.
|
2018-07-26 12:01:16 +00:00
|
|
|
|
|
|
|
|
|
* The `*`, `&` and `&&` declarators are grouped with the name, not the type
|
2023-03-26 16:23:17 +00:00
|
|
|
|
(classical C-style) as in `char *string` instead of `char* string`. This
|
2018-07-26 12:01:16 +00:00
|
|
|
|
reflects the precedence rules of the language: `int &i` means that the name
|
|
|
|
|
`i` stands for a reference [to an object with type `int`], not that
|
|
|
|
|
`i` stands for an object of the type [reference to `int`].
|
|
|
|
|
Although this may seem like hairsplitting (both interpretations
|
|
|
|
|
have the same effect) it is crucial in the
|
|
|
|
|
definition of multiple variables, such
|
|
|
|
|
as
|
2023-03-26 16:12:43 +00:00
|
|
|
|
```
|
|
|
|
|
struct dive *next, **pprev;
|
|
|
|
|
```
|
2014-07-16 16:16:47 +00:00
|
|
|
|
|
2024-09-06 20:16:28 +00:00
|
|
|
|
* We generally use explicit types in variable declarations for clarity.
|
2018-07-03 20:25:44 +00:00
|
|
|
|
Use `auto` sparingly and only in cases where code readability improves.
|
|
|
|
|
Two classical examples are:
|
|
|
|
|
- Iterators, whose type names often are verbose:
|
2023-03-26 16:12:43 +00:00
|
|
|
|
```
|
|
|
|
|
auto it = m_trackers.find(when);
|
|
|
|
|
```
|
|
|
|
|
is not only distinctly shorter than
|
|
|
|
|
```
|
2024-09-06 20:16:28 +00:00
|
|
|
|
std::map<qint64, gpsTracker>::iterator it = m_trackers.find(when);
|
2023-03-26 16:12:43 +00:00
|
|
|
|
```
|
|
|
|
|
it will also continue working if a different data structure is chosen.
|
2018-07-03 20:25:44 +00:00
|
|
|
|
- If the type is given in the same line anyway. Thus,
|
2023-03-26 16:12:43 +00:00
|
|
|
|
```
|
2024-09-06 20:16:28 +00:00
|
|
|
|
auto service = std::make_unique<QLowEnergyService*>(sender());
|
2023-03-26 16:12:43 +00:00
|
|
|
|
```
|
|
|
|
|
is easier to read than and conveys the same information as
|
|
|
|
|
```
|
2024-09-06 20:16:28 +00:00
|
|
|
|
std::unique_ptr<QLowEnergyService> service = std::make_unique<QLowEnergyService>(sender());
|
2023-03-26 16:12:43 +00:00
|
|
|
|
```
|
2024-09-06 20:16:28 +00:00
|
|
|
|
|
|
|
|
|
* containers
|
|
|
|
|
|
|
|
|
|
The standard library (STL) containers are robust, but their usage may
|
|
|
|
|
appear verbose. Therefore, we have a few convenience functions in the
|
|
|
|
|
`core/ranges.h` header.
|
|
|
|
|
For example, to loop with an index variable, use
|
|
|
|
|
```
|
|
|
|
|
for (auto [idx, v]: container) {
|
|
|
|
|
...
|
|
|
|
|
}
|
|
|
|
|
```
|
2019-04-01 20:15:19 +00:00
|
|
|
|
|
2018-04-14 11:03:19 +00:00
|
|
|
|
* text strings
|
2023-03-26 16:18:58 +00:00
|
|
|
|
|
2014-12-17 09:23:53 +00:00
|
|
|
|
The default language of subsurface is US English so please use US English
|
|
|
|
|
spelling and terminology.
|
2023-03-26 16:24:54 +00:00
|
|
|
|
User-visible strings should be passed to the `tr()` function to enable
|
2014-12-17 09:23:53 +00:00
|
|
|
|
translation into other languages.
|
2018-07-26 12:01:16 +00:00
|
|
|
|
- like this
|
|
|
|
|
```
|
2023-03-26 16:12:43 +00:00
|
|
|
|
QString msgTitle = tr("Check for updates.");
|
2018-07-26 12:01:16 +00:00
|
|
|
|
```
|
|
|
|
|
- rather than
|
|
|
|
|
```
|
2023-03-26 16:12:43 +00:00
|
|
|
|
QString msgTitle = "Check for updates.";
|
2018-07-26 12:01:16 +00:00
|
|
|
|
```
|
2014-12-17 09:23:53 +00:00
|
|
|
|
|
2023-03-26 16:24:54 +00:00
|
|
|
|
This works by default in classes (indirectly) derived from `QObject`. Each
|
2018-06-21 06:36:04 +00:00
|
|
|
|
string to be translated is associated with a context, which corresponds
|
2023-03-26 16:24:54 +00:00
|
|
|
|
to the class name. Classes that are not derived from `QObject` can generate
|
|
|
|
|
the `tr()` functions by using the `Q_DECLARE_TR_FUNCTIONS` macro:
|
2018-07-26 12:01:16 +00:00
|
|
|
|
```
|
2023-03-26 16:12:43 +00:00
|
|
|
|
#include <QCoreApplication>
|
|
|
|
|
|
|
|
|
|
class myClass {
|
|
|
|
|
Q_DECLARE_TR_FUNCTIONS(gettextfromC)
|
|
|
|
|
...
|
|
|
|
|
};
|
2018-07-26 12:01:16 +00:00
|
|
|
|
```
|
2018-06-21 06:36:04 +00:00
|
|
|
|
|
2023-03-26 16:24:54 +00:00
|
|
|
|
As an alternative, which also works outside of class context, the `tr()`
|
2018-06-21 06:36:04 +00:00
|
|
|
|
function of a different class can be called. This avoids creating multiple
|
|
|
|
|
translations for the same string:
|
2018-07-26 12:01:16 +00:00
|
|
|
|
```
|
2023-03-26 16:12:43 +00:00
|
|
|
|
gettextFromC::tr("%1km")
|
2018-07-26 12:01:16 +00:00
|
|
|
|
```
|
2018-06-21 06:36:04 +00:00
|
|
|
|
|
2023-03-26 16:24:54 +00:00
|
|
|
|
The `gettextFromC` class in the above example was created as a catch-all
|
2024-09-06 20:16:28 +00:00
|
|
|
|
context for translations accessed in core code. To use it from C, include
|
|
|
|
|
the `"core/gettext.h"` header and invoke the `translate()` macro:
|
2018-07-26 12:01:16 +00:00
|
|
|
|
```
|
2023-03-26 16:12:43 +00:00
|
|
|
|
#include "core/gettext.h"
|
|
|
|
|
|
|
|
|
|
report_error(translate("gettextFromC", "Remote storage and local data diverged"));
|
2018-07-26 12:01:16 +00:00
|
|
|
|
```
|
2023-03-26 16:24:54 +00:00
|
|
|
|
It is crucial to pass `"gettextFromC"` as a first macro argument so that Qt
|
2018-06-21 06:36:04 +00:00
|
|
|
|
is able to associate the string with the correct context.
|
|
|
|
|
The translate macro returns a cached C-style string, which is generated at runtime
|
|
|
|
|
when the particular translation string is encountered for the first time.
|
|
|
|
|
It remains valid during the whole application's life time.
|
|
|
|
|
|
2018-07-26 12:01:16 +00:00
|
|
|
|
Outside of function context, the `QT_TRANSLATE_NOOP` macro can be used as in
|
|
|
|
|
```
|
|
|
|
|
struct ws_info_t ws_info[100] = {
|
2023-03-26 16:12:43 +00:00
|
|
|
|
{ QT_TRANSLATE_NOOP("gettextFromC", "integrated"), 0 },
|
|
|
|
|
{ QT_TRANSLATE_NOOP("gettextFromC", "belt"), 0 },
|
|
|
|
|
{ QT_TRANSLATE_NOOP("gettextFromC", "ankle"), 0 },
|
|
|
|
|
{ QT_TRANSLATE_NOOP("gettextFromC", "backplate"), 0 },
|
|
|
|
|
{ QT_TRANSLATE_NOOP("gettextFromC", "clip-on"), 0 },
|
2018-07-26 12:01:16 +00:00
|
|
|
|
};
|
|
|
|
|
```
|
2023-03-26 16:24:54 +00:00
|
|
|
|
Note that here, the texts will be scheduled for translation with the `"gettextFromC"`
|
2018-06-21 06:36:04 +00:00
|
|
|
|
context, but the array is only initialized with the original text. The actual
|
2018-07-26 12:01:16 +00:00
|
|
|
|
translation has to be performed later in code. For C-code, the `QT_TRANSLATE_NOOP`
|
2023-03-26 16:24:54 +00:00
|
|
|
|
macro is defined in the `"core/gettext.h"` header.
|
2018-06-21 06:36:04 +00:00
|
|
|
|
|
2018-04-14 11:03:19 +00:00
|
|
|
|
* UI text style
|
2023-03-26 16:18:58 +00:00
|
|
|
|
|
2018-04-09 05:59:33 +00:00
|
|
|
|
These guidelines are designed to ensure consistency in presentation within
|
2014-12-17 09:23:53 +00:00
|
|
|
|
Subsurface.
|
2018-04-09 05:59:33 +00:00
|
|
|
|
Only the first word of multi-word text strings should be capitalized unless
|
|
|
|
|
a word would normally be capitalized mid-sentence, like Africa. This applies
|
2014-12-17 09:23:53 +00:00
|
|
|
|
to all UI text including menus, menu items, tool-tips, button text and label
|
|
|
|
|
text etc. e.g. "Check for updates" rather than "Check for Updates".
|
2018-04-09 05:59:33 +00:00
|
|
|
|
We also capitalize Subsurface (NOTE: not SubSurface) when referring to the
|
2014-12-17 09:23:53 +00:00
|
|
|
|
application itself.
|
|
|
|
|
Abbreviations should end with a period, e.g. "temp." not "temp" for
|
|
|
|
|
temperature
|
|
|
|
|
Numerals in chemical formulae should use subscript characters e.g. O₂ not O2
|
|
|
|
|
Partial pressures in Subsurface are, by convention, abbreviated with a single
|
|
|
|
|
"p" rather than 2, as in pO₂ not ppO₂
|
|
|
|
|
Where more than one term exists for something, please choose the one already
|
|
|
|
|
in use within Subsurface e.g. Cylinder vs. Tank.
|
|
|
|
|
|
|
|
|
|
|
2018-04-14 11:03:19 +00:00
|
|
|
|
* string manipulation
|
2023-03-26 16:18:58 +00:00
|
|
|
|
|
2024-09-06 20:16:28 +00:00
|
|
|
|
- user interface
|
2023-03-26 16:18:58 +00:00
|
|
|
|
|
2023-03-26 16:24:54 +00:00
|
|
|
|
In UI part of the code use of `QString` methods is preferred, see this pretty
|
|
|
|
|
good guide in [`QString` documentation][1]
|
2023-03-26 16:18:58 +00:00
|
|
|
|
|
2024-09-06 20:16:28 +00:00
|
|
|
|
- core components
|
|
|
|
|
|
|
|
|
|
In the core part of the code, std::string should be used.
|
|
|
|
|
|
|
|
|
|
* memory management in core
|
2023-03-26 16:18:58 +00:00
|
|
|
|
|
2024-09-06 20:16:28 +00:00
|
|
|
|
In core code, objects are typically stored in containers, such as `std::vector<>` or
|
|
|
|
|
as subobjects of classes.
|
|
|
|
|
|
|
|
|
|
If an object has to be allocated on the heap, the owner keeps an `std::unique_ptr`.
|
|
|
|
|
To transfer ownership, use `std::move()`.
|
|
|
|
|
|
|
|
|
|
* initialization and life time
|
|
|
|
|
|
|
|
|
|
By using subobjects, the life time of objects is well defined.
|
|
|
|
|
Consider a class A1 with the two subobjects B and C:
|
|
|
|
|
```
|
|
|
|
|
class A1 {
|
|
|
|
|
struct B;
|
|
|
|
|
struct C;
|
|
|
|
|
};
|
|
|
|
|
```
|
|
|
|
|
furthermode, consider a class A2 derived from A1 with the subobjects D and E:
|
|
|
|
|
```
|
|
|
|
|
class A2 : public A1 {
|
|
|
|
|
struct D;
|
|
|
|
|
struct E;
|
|
|
|
|
};
|
|
|
|
|
```
|
|
|
|
|
When creating an object of type A2, the constructors are run in the following order:
|
|
|
|
|
- B
|
|
|
|
|
- C
|
|
|
|
|
- A1
|
|
|
|
|
- D
|
|
|
|
|
- E
|
|
|
|
|
- A2
|
|
|
|
|
The destructors run in opposite order.
|
|
|
|
|
This means that C can *always* access B, but not vice-versa and so on.
|
|
|
|
|
|
|
|
|
|
Subobjects should be initialized using initializer lists, so that they are initoalized
|
|
|
|
|
only once.
|
|
|
|
|
|
|
|
|
|
* pointers and references
|
|
|
|
|
|
|
|
|
|
The difference between pointers and references can be confusing to C programmers,
|
|
|
|
|
as internally they are realized by the same mechanism. However, conceptually they
|
|
|
|
|
are different: a reference is a placeholder for a variable.
|
|
|
|
|
|
|
|
|
|
In particular this means two things:
|
|
|
|
|
- A reference cannot be 'reseated'. It stands for a different variable and only
|
|
|
|
|
that variable. There is no pointer arithmetic with references.
|
|
|
|
|
- A reference cannot be null. In fact any reasonable compiler will compile
|
|
|
|
|
```
|
|
|
|
|
void f(int &f) {
|
|
|
|
|
return &f == nullptr ? 1 : 2;
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
as
|
|
|
|
|
```
|
|
|
|
|
f(int&):
|
|
|
|
|
mov eax, 2
|
|
|
|
|
ret
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Thus, functions should in general take references, not pointers. A pointer argument is
|
|
|
|
|
basically only used if the argument is optional.
|
|
|
|
|
|
|
|
|
|
* output parameters
|
|
|
|
|
|
|
|
|
|
If a function returns multiple values, generally don't return them in output parameters,
|
|
|
|
|
but return a structure of multiple values. This can be used in structured bindings:
|
|
|
|
|
```
|
|
|
|
|
[val, i] = get_result();
|
|
|
|
|
```
|
2018-04-10 07:08:46 +00:00
|
|
|
|
|
2018-04-14 11:03:19 +00:00
|
|
|
|
## Sample Settings
|
|
|
|
|
|
|
|
|
|
### Emacs
|
2014-02-27 15:57:22 +00:00
|
|
|
|
|
2023-03-26 16:24:54 +00:00
|
|
|
|
These lines in your `.emacs` file should get you fairly close when it comes
|
2023-03-26 16:23:17 +00:00
|
|
|
|
to indentation – many of the other rules you have to follow manually
|
2014-02-27 15:57:22 +00:00
|
|
|
|
|
2018-04-14 11:03:19 +00:00
|
|
|
|
```
|
2014-02-27 15:57:22 +00:00
|
|
|
|
;; indentation
|
|
|
|
|
(defun c-lineup-arglist-tabs-only (ignored)
|
|
|
|
|
"Line up argument lists by tabs, not spaces"
|
|
|
|
|
(let* ((anchor (c-langelem-pos c-syntactic-element))
|
|
|
|
|
(column (c-langelem-2nd-pos c-syntactic-element))
|
|
|
|
|
(offset (- (1+ column) anchor))
|
|
|
|
|
(steps (floor offset c-basic-offset)))
|
|
|
|
|
(* (max steps 1)
|
|
|
|
|
c-basic-offset)))
|
|
|
|
|
|
|
|
|
|
(add-hook 'c-mode-common-hook
|
|
|
|
|
(lambda ()
|
|
|
|
|
;; Add kernel style
|
|
|
|
|
(c-add-style
|
|
|
|
|
"linux-tabs-only"
|
|
|
|
|
'("linux" (c-offsets-alist
|
|
|
|
|
(arglist-cont-nonempty
|
|
|
|
|
c-lineup-gcc-asm-reg
|
|
|
|
|
c-lineup-arglist-tabs-only))))))
|
|
|
|
|
|
|
|
|
|
(add-hook 'c-mode-hook
|
|
|
|
|
(lambda ()
|
|
|
|
|
(let ((filename (buffer-file-name)))
|
|
|
|
|
;; Enable kernel mode for the appropriate files
|
|
|
|
|
(setq indent-tabs-mode t)
|
|
|
|
|
(c-set-style "linux-tabs-only"))))
|
|
|
|
|
|
|
|
|
|
(add-hook 'c++-mode-hook
|
|
|
|
|
(lambda ()
|
|
|
|
|
(let ((filename (buffer-file-name)))
|
|
|
|
|
;; Enable kernel mode for the appropriate files
|
|
|
|
|
(setq indent-tabs-mode t)
|
|
|
|
|
(c-set-style "linux-tabs-only"))))
|
2018-04-14 11:03:19 +00:00
|
|
|
|
```
|
2014-02-27 15:57:22 +00:00
|
|
|
|
|
2018-04-14 11:03:19 +00:00
|
|
|
|
### QtCreator
|
2014-02-27 15:57:22 +00:00
|
|
|
|
|
|
|
|
|
These settings seem to get indentation right in QtCreator. Making TAB
|
|
|
|
|
always adjust indent makes it hard to add hard tabs before '\' when
|
|
|
|
|
creating continuing lines. Copying a tab with your mouse / ctrl-C and
|
|
|
|
|
inserting it with ctrl-V seems to work around that problem (use Command
|
|
|
|
|
instead of ctrl on your Mac)
|
2015-09-07 14:58:35 +00:00
|
|
|
|
Save this XML code below to a file, open Preferences (or Tools->Options)
|
|
|
|
|
in QtCreator, pick C++ in the left column and then click on Import...
|
|
|
|
|
to open the file you just created. Now you should have a "Subsurface"
|
|
|
|
|
style that you can select which should work well for our coding style.
|
2014-02-27 15:57:22 +00:00
|
|
|
|
|
2018-04-14 11:03:19 +00:00
|
|
|
|
```
|
2014-02-27 15:57:22 +00:00
|
|
|
|
<?xml version="1.0" encoding="UTF-8"?>
|
|
|
|
|
<!DOCTYPE QtCreatorCodeStyle>
|
|
|
|
|
<!-- Written by QtCreator 3.0.0, 2014-02-27T07:52:57. -->
|
|
|
|
|
<qtcreator>
|
|
|
|
|
<data>
|
|
|
|
|
<variable>CodeStyleData</variable>
|
|
|
|
|
<valuemap type="QVariantMap">
|
|
|
|
|
<value type="bool" key="AlignAssignments">false</value>
|
|
|
|
|
<value type="bool" key="AutoSpacesForTabs">false</value>
|
|
|
|
|
<value type="bool" key="BindStarToIdentifier">true</value>
|
|
|
|
|
<value type="bool" key="BindStarToLeftSpecifier">false</value>
|
|
|
|
|
<value type="bool" key="BindStarToRightSpecifier">false</value>
|
|
|
|
|
<value type="bool" key="BindStarToTypeName">false</value>
|
|
|
|
|
<value type="bool" key="ExtraPaddingForConditionsIfConfusingAlign">false</value>
|
|
|
|
|
<value type="bool" key="IndentAccessSpecifiers">false</value>
|
|
|
|
|
<value type="bool" key="IndentBlockBody">true</value>
|
|
|
|
|
<value type="bool" key="IndentBlockBraces">false</value>
|
|
|
|
|
<value type="bool" key="IndentBlocksRelativeToSwitchLabels">false</value>
|
|
|
|
|
<value type="bool" key="IndentClassBraces">false</value>
|
|
|
|
|
<value type="bool" key="IndentControlFlowRelativeToSwitchLabels">true</value>
|
|
|
|
|
<value type="bool" key="IndentDeclarationsRelativeToAccessSpecifiers">true</value>
|
|
|
|
|
<value type="bool" key="IndentEnumBraces">false</value>
|
|
|
|
|
<value type="bool" key="IndentFunctionBody">true</value>
|
|
|
|
|
<value type="bool" key="IndentFunctionBraces">false</value>
|
|
|
|
|
<value type="bool" key="IndentNamespaceBody">false</value>
|
|
|
|
|
<value type="bool" key="IndentNamespaceBraces">false</value>
|
|
|
|
|
<value type="int" key="IndentSize">8</value>
|
|
|
|
|
<value type="bool" key="IndentStatementsRelativeToSwitchLabels">true</value>
|
|
|
|
|
<value type="bool" key="IndentSwitchLabels">false</value>
|
|
|
|
|
<value type="int" key="PaddingMode">2</value>
|
|
|
|
|
<value type="bool" key="SpacesForTabs">false</value>
|
|
|
|
|
<value type="int" key="TabSize">8</value>
|
|
|
|
|
</valuemap>
|
|
|
|
|
</data>
|
|
|
|
|
<data>
|
|
|
|
|
<variable>DisplayName</variable>
|
|
|
|
|
<value type="QString">Subsurface</value>
|
|
|
|
|
</data>
|
|
|
|
|
</qtcreator>
|
2018-04-14 11:03:19 +00:00
|
|
|
|
```
|
2014-02-27 21:42:10 +00:00
|
|
|
|
|
2018-04-14 11:03:19 +00:00
|
|
|
|
### Vim
|
2014-02-27 21:42:10 +00:00
|
|
|
|
|
2014-02-28 09:09:18 +00:00
|
|
|
|
As everybody knows vim is a way better editor than emacs and thus needs to be
|
2023-03-26 16:24:54 +00:00
|
|
|
|
in this file too. Put this into your `.vimrc` and this should produce something
|
2014-02-27 21:42:10 +00:00
|
|
|
|
close to our coding standards.
|
|
|
|
|
|
2018-04-14 11:03:19 +00:00
|
|
|
|
```
|
2014-02-27 21:42:10 +00:00
|
|
|
|
" Subsurface coding style
|
|
|
|
|
filetype plugin indent on
|
|
|
|
|
filetype detect
|
2014-03-10 17:19:40 +00:00
|
|
|
|
set cindent tabstop=8 shiftwidth=8 cinoptions=l1,:0,(0,g0
|
2014-02-27 21:42:10 +00:00
|
|
|
|
|
|
|
|
|
" And some sane defaults, optional, but quite nice
|
|
|
|
|
set nocompatible
|
|
|
|
|
syntax on
|
|
|
|
|
colorscheme default
|
2014-03-10 17:19:40 +00:00
|
|
|
|
set hls
|
|
|
|
|
set is
|
2014-02-27 21:42:10 +00:00
|
|
|
|
|
|
|
|
|
" The default blue is just impossible to see on a black terminal
|
|
|
|
|
highlight Comment ctermfg=Brown
|
|
|
|
|
|
|
|
|
|
" clearly point out when someone have trailing spaces
|
|
|
|
|
highlight ExtraWhitespace ctermbg=red guibg=red
|
|
|
|
|
|
|
|
|
|
" Show trailing whitespace and spaces before a tab:
|
|
|
|
|
match ExtraWhitespace /\s\+$\| \+\ze\t/
|
2018-04-14 11:03:19 +00:00
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
[1]: http://doc.qt.io/qt-5/qstring.html#manipulating-string-data
|
2020-04-26 23:36:27 +00:00
|
|
|
|
[2]: https://github.com/Subsurface/subsurface/blob/master/core/membuffer.h
|