|
1 | 1 |
|
2 |
| -=== Example Code Following Style === |
| 2 | +/* |
| 3 | + * Code style guidelines by example (or see .clang-format for an approximation |
| 4 | + * of how to automate part of this) |
| 5 | + */ |
3 | 6 |
|
| 7 | +/* |
| 8 | + * Do not use "typedef", always use "using". The "using" construct actually gets |
| 9 | + * the order sane. Make type aliases whenever it seems useful. Do not hold back, |
| 10 | + * especially if the type is long or *could ever change*. |
| 11 | + */ |
4 | 12 | using NodeType = uint16_t;
|
5 | 13 |
|
| 14 | +struct OtherClass { |
| 15 | + virtual void myTestMethod(int a) = 0; |
| 16 | +}; |
| 17 | + |
| 18 | +// Prefer "struct" over "class" |
| 19 | +template <typename T, typename U = void> |
6 | 20 | struct MyClassName : OtherClass {
|
7 |
| - // if it is above 80 cols, wrap to next line with regular identing |
8 |
| - static inline typename Abc<T,X>::type my_simple_method( |
| 21 | + |
| 22 | + using MyIntType = int32_t; |
| 23 | + using IteratorType = typename std::vector<MyIntType>::const_reverse_iterator; |
| 24 | + |
| 25 | + // Use defaults when possible and needed |
| 26 | + MyClassName() = default; |
| 27 | + MyClassName(MyClassName&&) = default; |
| 28 | + MyClassName(MyClassName const&) = default; |
| 29 | + |
| 30 | + // Often your destructor should be virtual |
| 31 | + virtual ~MyClassName() = default; |
| 32 | + |
| 33 | + // if it is above 80 cols, wrap to next line with regular indenting |
| 34 | + static inline typename Abc<T,X>::type mySimpleMethod( |
9 | 35 | int a, int b, int c, int d
|
10 | 36 | );
|
11 | 37 |
|
12 |
| - static void my_test(int a) { |
13 |
| - int a; |
14 |
| - int tmp; |
| 38 | + // Use the override keyword, it can only help you |
| 39 | + void myTestMethod(int a) override { |
| 40 | + // Initialize stack variables as much as possible (and static when possible) |
| 41 | + int a = 0, tmp = 0; |
15 | 42 | int my_local_count = 0;
|
| 43 | + std::vector<int> my_vec = {}; |
| 44 | + |
| 45 | + /* |
| 46 | + * Don't be afraid to use "and" or "or" or "not_eq". Often it's more |
| 47 | + * readable. It's fully C++ standard compliant. |
| 48 | + */ |
| 49 | + if (my_local_count != 0 and a == 0) { |
| 50 | + a = 10; |
| 51 | + } |
| 52 | + |
| 53 | + // Braces instead of semicolon when empty |
| 54 | + while (true) { } |
| 55 | + |
| 56 | + // Prefer spacing here |
| 57 | + for (int i = 0; i < 10; i++) { |
| 58 | + |
| 59 | + } |
| 60 | + |
| 61 | + for (auto&& elm : my_vec) { } |
16 | 62 | }
|
17 | 63 |
|
18 |
| - // if function returns bool, it should start with "is" or "has" |
19 |
| - bool isValid(); |
20 |
| - bool hasValue(); |
| 64 | + // if function returns bool, don't make the name too complicated |
| 65 | + bool valid() const; |
21 | 66 |
|
22 | 67 | private:
|
| 68 | + // Private members have trailing underscore |
23 | 69 | int my_data_;
|
24 |
| - bool is_coll; // if data is boolean, it should start with "is" or "has" |
| 70 | + bool is_coll_; // if data is boolean, it should start with "is" or "has" |
25 | 71 | };
|
26 | 72 |
|
27 |
| -enum eMyEnum { |
28 |
| - ConstantOne = 0, |
29 |
| - ConstantTwo = 1, |
| 73 | +/* |
| 74 | + * Wrap typename args when they get long, start ">" on next line, indented as |
| 75 | + * so. Use "typename" unless you have to use "class": exception being template |
| 76 | + * templates. Space goes here: "template <". Ellipses on on LHS for parameter |
| 77 | + * packs |
| 78 | + */ |
| 79 | +template < |
| 80 | + typename CollectionT, typename IndexT, typename TupleT, typename RetT, |
| 81 | + typename... Args |
| 82 | +> |
| 83 | +struct ManyTemplateParams { |
| 84 | + // Wrap function args when they get long, indented as so |
| 85 | + RetT operator()( |
| 86 | + CollectionT const& col, IndexT const& idx, TupleT&& tup, |
| 87 | + std::tuple<Args...> tup, std::unique_ptr<intt64_t> ptr |
| 88 | + ) { |
| 89 | + return {}; |
| 90 | + } |
30 | 91 | };
|
31 | 92 |
|
| 93 | +/* |
| 94 | + * Use an enum struct when possible. Degrading automatically (happens with |
| 95 | + * non-strongly typed enums) may introduce bugs |
| 96 | + */ |
32 | 97 |
|
33 |
| -template <typename T> |
34 |
| -struct A { |
35 |
| - |
| 98 | +enum struct CallbackEnum : int32_t { |
| 99 | + ConstantOne = 0, |
| 100 | + ConstantTwo = 1 |
36 | 101 | };
|
37 | 102 |
|
| 103 | +// A new line should be after the template, even in cases like this: |
| 104 | +template <typename T> |
| 105 | +struct A; |
| 106 | + |
| 107 | +// Use tag types when necessary. Name the type *Type explicitly, tag without |
| 108 | + |
| 109 | +struct MyTagType { } MyTag { }; |
| 110 | + |
| 111 | +/* |
| 112 | + * Do not indent code under a namespace. Always combine multiple nested |
| 113 | + * namespaces in one line (makes it easier to identify the full namespace path) |
| 114 | + * unless you need to wrap, then try to semantically group them |
| 115 | + */ |
38 | 116 |
|
39 |
| -Suggestion: |
40 |
| - |
41 |
| -- Use a space in between template and the bracket. |
42 |
| -- Use “typename” instead of “class” for all possible cases (the only time you have to use “class” is when you have a “template template”). |
43 |
| - |
44 |
| -Namespaces: |
45 |
| - |
46 |
| -- Do not indent code under a namespace. |
47 |
| -- Always combine multiple nested namespaces in one line (makes it easier to identify the full namespace path) |
48 |
| - |
49 | 117 | namespace X { namespace Y {
|
50 |
| - |
51 |
| -}} // end namespace X::Y |
| 118 | + |
| 119 | +}} // end namespace X::Y |
0 commit comments