blob: 201209382c1a606930ef626fc847c9fbe99c7b2e [file] [log] [blame]
Alexander Afanasyev766cea72014-04-24 19:16:42 -07001ndn-cxx Code Style and Coding Guidelines
2========================================
Alexander Afanasyev3aeeaeb2014-04-22 23:34:23 -07003
4Based on
5
6 * "C++ Programming Style Guidelines" by Geotechnical Software Services, Copyright © 1996 – 2011.
7 The original document is available at `<http://geosoft.no/development/cppstyle.html>`_
8
9 * NDN Platform "C++, C, C#, Java and JavaScript Code Guidelines".
10 The original document available at `<http://named-data.net/codebase/platform/documentation/ndn-platform-development-guidelines/cpp-code-guidelines/>`_
11
121. Code layout and file naming
13------------------------------
14
151.1. The code layout should generally follow the GNU coding standard layout for C,
16extended it to C++.
17
18 * Do not use tabs for indentation.
19 * Indentation spacing is 2 spaces.
20 * Lines should be within a reasonable range. Lines longer than 100 columns should
21 generally be avoided.
22
231.2. Whitespace
24
25 * Conventional operators (``if``, ``for``, ``while``, and others) should be
26 surrounded by a space character.
27 * Commas should be followed by a white space.
28 * Semicolons in for statments should be followed by a space character.
29
30 Examples:
31
32 .. code-block:: c++
33
34 a = (b + c) * d; // NOT: a=(b+c)*d
35
36 while (true) { // NOT: while(true)
37 ...
38
39 doSomething(a, b, c, d); // NOT: doSomething(a,b,c,d);
40
41 for (i = 0; i < 10; i++) { // NOT: for(i=0;i<10;i++){
42 ...
43
441.3. Namespaces should have the following form:
45
46 .. code-block:: c++
47
48 namespace example {
49
50 code;
51 moreCode;
52
53 } // namespace example
54
55 Note that code inside namespace is **not** indented. Avoid following:
56
57 .. code-block:: c++
58
59 // NOT
60 //
61 // namespace example {
62 //
63 // code;
64 // moreCode;
65 //
66 // } // namespace example
67
681.4. The class declarations should have the following form:
69
70 .. code-block:: c++
71
72 class SomeClass : public BaseClass
73 {
74 public:
75 ... <public methods> ...
76 protected:
77 ... <protected methods> ...
78 private:
79 ... <private methods> ...
80
81 public:
82 ... <public data> ...
83 protected:
84 ... <protected data> ...
85 private:
86 ... <private data> ...
87 };
88
89 ``public``, ``protected``, ``private`` may be repeated several times without
90 interleaving (e.g., public, public, public, private, private) if this allows better
91 readability of the code.
92
93 Nested classes can be defined in appropriate visibility section, either in methods
94 block, data block, or in a separate section (depending which one provides better code
95 readability).
96
971.5. Method and function definitions should have the following form:
98
99 .. code-block:: c++
100
101 void
102 someMethod()
103 {
104 ...
105 }
106
107 void
108 SomeClass::someMethod()
109 {
110 ...
111 }
112
1131.6. The ``if-else`` class of statements should have the following form:
114
115 .. code-block:: c++
116
117 if (condition) {
118 statements;
119 }
120
121 if (condition) {
122 statements;
123 }
124 else {
125 statements;
126 }
127
128 if (condition) {
129 statements;
130 }
131 else if (condition) {
132 statements;
133 }
134 else {
135 statements;
136 }
137
138 or (less preferred):
139
140 .. code-block:: c++
141
142 if (condition)
143 {
144 statements;
145 }
146 else if (condition)
147 {
148 statements;
149 }
150 else
151 {
152 statements;
153 }
154
1551.7. A ``for`` statement should have the following form:
156
157 .. code-block:: c++
158
159 for (initialization; condition; update) {
160 statements;
161 }
162
163 or (less preferred):
164
165 .. code-block:: c++
166
167 for (initialization; condition; update)
168 {
169 statements;
170 }
171
172 An empty for statement should have the following form:
173
174 .. code-block:: c++
175
176 for (initialization; condition; update)
177 ;
178
179 This emphasizes the fact that the for statement is empty and it makes it obvious for
180 the reader that this is intentional. Empty loops should be avoided however.
181
1821.8. A ``while`` statement should have the following form:
183
184 .. code-block:: c++
185
186 while (condition) {
187 statements;
188 }
189
190 or (less preferred):
191
192 .. code-block:: c++
193
194 while (condition)
195 {
196 statements;
197 }
198
1991.9. A ``do-while`` statement should have the following form:
200
201 .. code-block:: c++
202
203 do {
204 statements;
205 } while (condition);
206
2071.10. A ``switch`` statement should have the following form:
208
209 .. code-block:: c++
210
211 switch (condition) {
212 case ABC:
213 statements;
214 // Fallthrough
215
216 case DEF:
217 statements;
218 break;
219
220 case XYZ:
221 statements;
222 break;
223
224 default:
225 statements;
226 break;
227 }
228
229 or (less preferred):
230
231 .. code-block:: c++
232
233 switch (condition)
234 {
235 case ABC:
236 statements;
237 // Fallthrough
238
239 case DEF:
240 statements;
241 break;
242
243 case XYZ:
244 statements;
245 break;
246
247 default:
248 statements;
249 break;
250 }
251
252 The explicit ``Fallthrough`` comment should be included whenever there is a case
253 statement without a break statement. Leaving the break out is a common error, and it
254 must be made clear that it is intentional when it is not there.
255
2561.11. A ``try-catch`` statement should have the following form:
257
258 .. code-block:: c++
259
260 try {
261 statements;
262 }
263 catch (Exception& exception) {
264 statements;
265 }
266
267 or (less preferred):
268
269 .. code-block:: c++
270
271 try
272 {
273 statements;
274 }
275 catch (Exception& exception)
276 {
277 statements;
278 }
279
2801.12. The incompleteness of split lines must be made obvious.
281
282 .. code-block:: c++
283
284 totalSum = a + b + c +
285 d + e;
286 function(param1, param2,
287 param3);
288 for (int tableNo = 0; tableNo < nTables;
289 tableNo += tableStep) {
290 ...
291 }
292
293 Split lines occurs when a statement exceed the 80 column limit given above. It is
294 difficult to give rigid rules for how lines should be split, but the examples above should
295 give a general hint.In general:
296
297 * Break after a comma.
298 * Break after an operator.
299 * Align the new line with the beginning of the expression on the previous line.
300
301 Exceptions:
302
303 * The following is the standard practice with operator<<:
304
305 .. code-block:: c++
306
307 std::cout << "Something here "
308 << "Something there" << std::endl;
309
3101.13. When class variables need to be initialized in the constructor, the initialization
311should take the following form:
312
313 .. code-block:: c++
314
315 SomeClass::SomeClass(int value, const std::string& string)
316 : m_value(value)
317 , m_string(string)
318 ...
319 {
320 }
321
322 Each initialization should be put on a separate line, starting either with the colon
323 for the first initialization or with comma for all subsequent initializations.
324
Junxiao Shi45c13842014-11-02 15:36:04 -07003251.14. A range-based ``for`` statement should have the following form:
326
327 .. code-block:: c++
328
329 for (T i : range) {
330 statements;
331 }
332
Alexander Afanasyev3aeeaeb2014-04-22 23:34:23 -07003332. Naming Conventions
334---------------------
335
3362.1. C++ header files should have the extension ``.hpp``. Source files should have the
337extension ``.cpp``
338
339 File names should be all lower case. If the class name
340 is a composite of several words, each word in a file name should be separated with a
341 dash (-). A class should be declared in a header file and defined in a source file
342 where the name of the files match the name of the class.
343
344 ::
345
346 my-class.hpp, my-class.cpp
347
348
3492.2. Names representing types must be written in English in mixed case starting with upper case.
350
351 .. code-block:: c++
352
353 class MyClass;
354 class Line;
355 class SavingsAccount;
356
3572.3. Variable names must be written in English in mixed case starting with lower case.
358
359 .. code-block:: c++
360
361 MyClass myClass;
362 Line line;
363 SavingsAccount savingsAccount;
364 int theAnswerToLifeTheUniverseAndEverything;
365
3662.4. Named constants (including enumeration values) must be all uppercase using underscore
367to separate words.
368
369 .. code-block:: c++
370
371 const int MAX_ITERATIONS = 25;
372 const std::string COLOR_RED = "red";
373 static const double PI = 3.14;
374
375 In some cases, it is a better (or is the only way for complex constants in header-only
376 classes) to implement the value as a method:
377
378 .. code-block:: c++
379
380 int
381 getMaxIterations()
382 {
383 return 25;
384 }
385
3862.5. Names representing methods or functions must be commands starting with a verb and
387written in mixed case starting with lower case.
388
389 .. code-block:: c++
390
391 std::string
392 getName()
393 {
394 ...
395 }
396
397 double
398 computeTotalWidth()
399 {
400 ...
401 }
402
4032.6. Names representing namespaces should be all lowercase.
404
405 .. code-block:: c++
406
407 namespace model {
408 namespace analyzer {
409
410 ...
411
412 } // namespace analyzer
413 } // namespace model
414
4152.7. Names representing generic template types should be a single uppercase letter
416
417 .. code-block:: c++
418
419 template<class T> ...
420 template<class C, class D> ...
421
422 However, when template parameter represents a certain concept and expected to have a
423 certain interface, the name should be explicitly spelled out:
424
425 .. code-block:: c++
426
427 template<class FaceBase> ...
428 template<class Packet> ...
429
4302.8. Abbreviations and acronyms must not be uppercase when used as name.
431
432 .. code-block:: c++
433
434 exportHtmlSource(); // NOT: exportHTMLSource();
435 openDvdPlayer(); // NOT: openDVDPlayer();
436
4372.9. Global variables should have ``g_`` prefix
438
439 .. code-block:: c++
440
441 g_mainWindow.open();
442 g_applicationContext.getName();
443
444 In general, the use of global variables should be avoided. Consider using singleton
445 objects instead.
446
4472.10. Private class variables should have ``m_`` prefix. Static class variables should have
448``s_`` prefix.
449
450 .. code-block:: c++
451
452 class SomeClass
453 {
454 private:
455 int m_length;
456
457 static std::string s_name;
458 };
459
460
4612.11. Variables with a large scope should have long (explicit) names, variables with a small
462scope can have short names.
463
464 Scratch variables used for temporary storage or indices are best kept short. A
465 programmer reading such variables should be able to assume that its value is not used
466 outside of a few lines of code. Common scratch variables for integers are ``i``,
467 ``j``, ``k``, ``m``, ``n`` and for characters ``c`` and ``d``.
468
4692.12. The name of the object is implicit, and should be avoided in a method name.
470
471 .. code-block:: c++
472
473 line.getLength(); // NOT: line.getLineLength();
474
475 The latter seems natural in the class declaration, but proves superfluous in use, as
476 shown in the example.
477
4782.13. The terms ``get/set`` must be used where an attribute is accessed directly.
479
480 .. code-block:: c++
481
482 employee.getName();
483 employee.setName(name);
484
485 matrix.getElement(2, 4);
486 matrix.setElement(2, 4, value);
487
4882.14. The term ``compute`` can be used in methods where something is computed.
489
490 .. code-block:: c++
491
492 valueSet.computeAverage();
493 matrix.computeInverse()
494
495 Give the reader the immediate clue that this is a potentially time-consuming operation,
496 and if used repeatedly, he might consider caching the result. Consistent use of the term
497 enhances readability.
498
4992.15. The term ``find`` can be used in methods where something is looked up.
500
501 .. code-block:: c++
502
503 vertex.findNearestVertex();
504 matrix.findMinElement();
505
506 Give the reader the immediate clue that this is a simple look up method with a minimum
507 of computations involved. Consistent use of the term enhances readability.
508
5092.16. Plural form should be used on names representing a collection of objects.
510
511 .. code-block:: c++
512
513 vector<Point> points;
514 int values[];
515
516 Enhances readability since the name gives the user an immediate clue of the type of
517 the variable and the operations that can be performed on its elements.
518
5192.17. The prefix ``n`` should be used for variables representing a number of objects.
520
521 .. code-block:: c++
522
523 nPoints, nLines
524
525 The notation is taken from mathematics where it is an established convention for
526 indicating a number of objects.
527
528
5292.18. The suffix ``No`` should be used for variables representing an entity number.
530
531 .. code-block:: c++
532
533 tableNo, employeeNo
534
535 The notation is taken from mathematics where it is an established convention for
536 indicating an entity number. An elegant alternative is to prefix such variables with
537 an ``i``: ``iTable``, ``iEmployee``. This effectively makes them named iterators.
538
5392.19. The prefix ``is``, ``has``, ``need``, or similar should be used for boolean variables and
540methods.
541
542 .. code-block:: c++
543
544 isSet, isVisible, isFinished, isFound, isOpen
545 needToConvert, needToFinish
546
5472.20. Complement names must be used for complement operations, reducing complexity by
548symmetry.
549
550 ::
551
552 get/set, add/remove, create/destroy, start/stop, insert/delete,
553 increment/decrement, old/new, begin/end, first/last, up/down, min/max,
554 next/previous (and commonly used next/prev), open/close, show/hide,
555 suspend/resume, etc.
556
557 Pair ``insert/erase`` should be preferred. ``insert/delete`` can also be used if it
558 does not conflict with C++ delete keyword.
559
5602.21. Variable names should not include reference to variable type (do not use Hungarian
561notation).
562
563 .. code-block:: c++
564
565 Line* line; // NOT: Line* pLine;
566 // NOT: Line* linePtr;
567
568 size_t nPoints; // NOT lnPoints
569
570 char* name; // NOT szName
571
5722.22. Negated boolean variable names should be avoided.
573
574 .. code-block:: c++
575
576 bool isError; // NOT: isNoError
577 bool isFound; // NOT: isNotFound
578
5792.23. Enumeration constants recommended to prefix with a common type name.
580
581 .. code-block:: c++
582
583 enum Color {
584 COLOR_RED,
585 COLOR_GREEN,
586 COLOR_BLUE
587 };
588
5892.24. Exceptions can be suffixed with either ``Exception`` (e.g., ``SecurityException``) or
590``Error`` (e.g., ``SecurityError``).
591
592 The recommended method is to declare exception class ``Exception`` or ``Error`` as an
593 inner class, from which the exception is thrown. For example, when declaring class
594 ``Foo`` that can throw errors, one can write the following:
595
596 .. code-block:: c++
597
598 #include <stdexcept>
599
600 class Foo
601 {
602 class Error : public std::runtime_error
603 {
604 public:
605 explicit
606 Error(const std::string& what)
607 : std::runtime_error(what)
608 {
609 }
610 };
611 };
612
613 In addition to that, if class Foo is a base class or interface for some class
614 hierarchy, then child classes should should define their own ``Error`` or
615 ``Exception`` classes that are inherited from the parent's Error class.
616
617
6182.25. Functions (methods returning something) should be named after what they return and
619procedures (void methods) after what they do.
620
621 Increase readability. Makes it clear what the unit should do and especially all the
622 things it is not supposed to do. This again makes it easier to keep the code clean of
623 side effects.
624
6253. Miscellaneous
626----------------
627
6283.1. Exceptions can be used in the code, but should be used only in exceptional cases and
629not in the primary processing path.
630
6313.2. Header files must contain an include guard.
632
633 For example, header file located in ``module/class-name.hpp`` or in
634 ``src/module/class-name.hpp`` should have header guard in the following form:
635
636 .. code-block:: c++
637
638 #ifndef APP_MODULE_CLASS_NAME_HPP
639 #define APP_MODULE_CLASS_NAME_HPP
640 ...
641 #endif // APP_MODULE_CLASS_NAME_HPP
642
643 The name should follow the location of the file inside the source tree and prevents
644 naming conflicts. Header guard should be prefixed with the application/library name
645 to avoid conflicts with other packaged and libraries.
646
6473.3. Header files which are in the same source distribution should be included in
648``"quotes"``, if possible with a path relative to the source file. Header files for
649system and other external libraries should be included in ``<angle brackets>``.
650
651 .. code-block:: c++
652
653 #include <string>
654 #include <boost/lexical_cast.hpp>
655
656 #include "util/random.hpp"
657
6583.4. Include statements should be sorted and grouped. Sorted by their hierarchical position
659in the system with low level files included first. Leave an empty line between groups
660of include statements.
661
662 .. code-block:: c++
663
664 #include <fstream>
665 #include <iomanip>
666
667 #include <boost/lexical_cast.hpp>
668 #include <boost/regex.hpp>
669
670 #include "detail/pending-interest.hpp"
671 #include "util/random.hpp"
672
673
6743.5. Types that are local to one file only can be declared inside that file.
675
676
6773.6. Implicit conversion is generally allowed.
678
679 Implicit conversion between integer and floating point numbers can cause problems and
680 should be avoided.
681
682 Implicit conversion in single-argument constructor is usually undesirable. Therefore, all
683 single-argument constructors should be marked 'explicit', unless implicit conversion is
684 desirable. In that case, a comment should document the reason.
685
686 Avoid C-style casts. Use ``static_cast``, ``dynamic_cast``, ``reinterpret_cast``,
687 ``const_cast`` instead where appropriate. Use ``static_pointer_cast``,
688 ``dynamic_pointer_cast``, ``const_pointer_cast`` when dealing with ``shared_ptr``.
689
690
6913.7. Variables should be initialized where they are declared.
692
693 This ensures that variables are valid at any time. Sometimes it is impossible to
694 initialize a variable to a valid value where it is declared:
695
696 .. code-block:: c++
697
698 int x, y, z;
699 getCenter(&x, &y, &z);
700
701 In these cases it should be left uninitialized rather than initialized to some phony
702 value.
703
7043.8. In most cases, class instance variables should not be declared public.
705
706 The concepts of information hiding and encapsulation are violated by public variables. Use
707 private variables and access methods instead.
708
709 Exceptions to this rule:
710
711 * when the class is essentially a dumb data structure with no or minimal behavior
712 (equivalent to a C struct, also known as PODS). In this case it is appropriate to make
713 the instance variables public by using struct.
714
715 * when the class is used only inside the compilation unit, e.g., when implementing pImpl
716 idiom (aka Bridge pattern) or similar cases.
717
718
7193.9. C++ pointers and references should have their reference symbol next to the type rather
720than to the name.
721
722 .. code-block:: c++
723
724 float* x; // NOT: float *x;
725 int& y; // NOT: int &y;
726
7273.10. Implicit test for 0 should not be used other than for boolean variables and pointers.
728
729 .. code-block:: c++
730
731 if (nLines != 0) // NOT: if (nLines)
732 if (value != 0.0) // NOT: if (value)
733
7343.11. When checking if ``shared_ptr`` points to an object, explicit ``static_cast<bool>``
735must be used.
736
737 ``shared_ptr`` in C++11 (unlike ``boost::shared_ptr``) does not have implicit
738 conversion to bool.
739
7403.12. Loop variables should be initialized immediately before the loop.
741
742 .. code-block:: c++
743
744 isDone = false; // NOT: bool isDone = false;
745 while (!isDone) { // // other stuff
746 : // while (!isDone) {
747 } // :
748 // }
749
7503.13. The form while (true) should be used for infinite loops.
751
752 .. code-block:: c++
753
754 while (true) {
755 ...
756 }
757
758 // NOT:
759 for (;;) { // NO!
760 :
761 }
762 while (1) { // NO!
763 :
764 }
765
7663.14. Complex conditional expressions must be avoided. Introduce temporary boolean variables
767instead.
768
769 .. code-block:: c++
770
771 bool isFinished = (elementNo < 0) || (elementNo > maxElement);
772 bool isRepeatedEntry = elementNo == lastElement;
773 if (isFinished || isRepeatedEntry) {
774 ...
775 }
776
777 // NOT:
778 // if ((elementNo < 0) || (elementNo > maxElement) || elementNo == lastElement) {
779 // ...
780 // }
781
782 By assigning boolean variables to expressions, the program gets automatic
783 documentation. The construction will be easier to read, debug and maintain.
784
7853.15. The conditional should be put on a separate line.
786
787 .. code-block:: c++
788
789 if (isDone) // NOT: if (isDone) doCleanup();
790 doCleanup();
791
792 This is for debugging purposes. When writing on a single line, it is not apparent
793 whether the test is really true or not.
794
7953.16. Assignment statements in conditionals must be avoided.
796
797 .. code-block:: c++
798
799 File* fileHandle = open(fileName, "w");
800 if (!fileHandle) {
801 ...
802 }
803
804 // NOT
805 // if (!(fileHandle = open(fileName, "w"))) {
806 // ..
807 // }
808
8093.17. The use of magic numbers in the code should be avoided. Numbers other than 0 and 1
810should be considered declared as named constants instead.
811
812 If the number does not have an obvious meaning by itself, the readability is enhanced
813 by introducing a named constant instead. A different approach is to introduce a method
814 from which the constant can be accessed.
815
8163.18. Floating point constants should always be written with decimal point, at least one
817 decimal, and without omitting 0 before decimal point.
818
819 .. code-block:: c++
820
821 double total = 0.0; // NOT: double total = 0;
822 double someValue = 0.1; // NOT double someValue = .1;
823 double speed = 3.0e8; // NOT: double speed = 3e8;
824 double sum;
825 ...
826 sum = (a + b) * 10.0;
827
8283.19. ``goto`` should not be used.
829
830Goto statements violate the idea of structured code. Only in some very few cases (for
831instance breaking out of deeply nested structures) should goto be considered, and only if
832the alternative structured counterpart is proven to be less readable.
833
Junxiao Shi03b15b32014-10-30 21:10:25 -07008343.20. ``nullptr`` should be used to represent a null pointer, instead of "0" or "NULL".
Alexander Afanasyev3aeeaeb2014-04-22 23:34:23 -0700835
8363.21. Logical units within a block should be separated by one blank line.
837
838 .. code-block:: c++
839
840 Matrix4x4 matrix = new Matrix4x4();
841
842 double cosAngle = Math.cos(angle);
843 double sinAngle = Math.sin(angle);
844
845 matrix.setElement(1, 1, cosAngle);
846 matrix.setElement(1, 2, sinAngle);
847 matrix.setElement(2, 1, -sinAngle);
848 matrix.setElement(2, 2, cosAngle);
849
850 multiply(matrix);
851
852 Enhance readability by introducing white space between logical units of a block.
853
8543.22. Variables in declarations can be left aligned.
855
856 .. code-block:: c++
857
858 AsciiFile* file;
859 int nPoints;
860 float x, y;
861
862 Enhance readability. The variables are easier to spot from the types by alignment.
863
8643.23. Use alignment wherever it enhances readability.
865
866 .. code-block:: c++
867
868 value = (potential * oilDensity) / constant1 +
869 (depth * waterDensity) / constant2 +
870 (zCoordinateValue * gasDensity) / constant3;
871
872 minPosition = computeDistance(min, x, y, z);
873 averagePosition = computeDistance(average, x, y, z);
874
875 There are a number of places in the code where white space can be included to enhance
876 readability even if this violates common guidelines. Many of these cases have to do
877 with code alignment. General guidelines on code alignment are difficult to give, but
878 the examples above should give a general clue.
879
8803.24. All comments should be written in English.
881
882 In an international environment English is the preferred language.
883
Alexander Afanasyevdfa52c42014-04-24 21:10:11 -07008843.25. Use ``//`` for all comments, including multi-line comments.
Alexander Afanasyev3aeeaeb2014-04-22 23:34:23 -0700885
886 .. code-block:: c++
887
888 // Comment spanning
889 // more than one line.
890
891 Since multilevel C-commenting is not supported, using ``//`` comments ensure that it
892 is always possible to comment out entire sections of a file using ``/* */`` for
893 debugging purposes etc.
894
895 There should be a space between the ``//`` and the actual comment, and comments should
896 always start with an upper case letter and end with a period.
897
898 However, method and class documentation comments should use ``/** */`` style for
899 Doxygen, JavaDoc and JSDoc.
900
9013.26. Comments should be included relative to their position in the code.
902
903 .. code-block:: c++
904
905 while (true) {
906 // Do something
907 something();
908 }
909
910 // NOT:
911 while (true) {
912 // Do something
913 something();
914 }
915
916 This is to avoid that the comments break the logical structure of the program.
Junxiao Shiae61aac2014-11-04 14:57:38 -0700917
9183.27. Use ``BOOST_ASSERT`` and ``BOOST_ASSERT_MSG`` for runtime assertions.
919
920 .. code-block:: c++
921
922 int x = 1;
923 int y = 2;
924 int z = x + y;
925 BOOST_ASSERT(z - y == x);
926
927 The expression passed to ``BOOST_ASSERT`` MUST NOT have side effects,
928 because it MAY NOT be evaluated in release builds.
929
9303.28. Use ``static_assert`` for static assertions.
931
932
933 .. code-block:: c++
934
935 class BaseClass
936 {
937 };
938
939 class DerivedClass : public BaseClass
940 {
941 };
942
943 static_assert(std::is_base_of<BaseClass, DerivedClass>::value,
944 "DerivedClass must inherit from BaseClass");