1Using C++ in Mozilla code
2=========================
3
4C++ language features
5---------------------
6
7Mozilla code only uses a subset of C++. Runtime type information (RTTI)
8is disabled, as it tends to cause a very large increase in codesize.
9This means that ``dynamic_cast``, ``typeid()`` and ``<typeinfo>`` cannot
10be used in Mozilla code. Also disabled are exceptions; do not use
11``try``/``catch`` or throw any exceptions. Libraries that throw
12exceptions may be used if you are willing to have the throw instead be
13treated as an abort.
14
15On the side of extending C++, we compile with ``-fno-strict-aliasing``.
16This means that when reinterpreting a pointer as a differently-typed
17pointer, you don't need to adhere to the "effective type" (of the
18pointee) rule from the standard (aka. "the strict aliasing rule") when
19dereferencing the reinterpreted pointer. You still need make sure that
20you don't violate alignment requirements and need to make sure that the
21data at the memory location pointed to forms a valid value when
22interpreted according to the type of the pointer when dereferencing the
23pointer for reading. Likewise, if you write by dereferencing the
24reinterpreted pointer and the originally-typed pointer might still be
25dereferenced for reading, you need to make sure that the values you
26write are valid according to the original type. This value validity
27issue is moot for e.g. primitive integers for which all bit patterns of
28their size are valid values.
29
30-  As of Mozilla 59, C++14 mode is required to build Mozilla.
31-  As of Mozilla 67, MSVC can no longer be used to build Mozilla.
32-  As of Mozilla 73, C++17 mode is required to build Mozilla.
33
34This means that C++17 can be used where supported on all platforms. The
35list of acceptable features is given below:
36
37.. list-table::
38   :widths: 25 25 25 25
39   :header-rows: 3
40
41   * -
42     - GCC
43     - Clang
44     -
45   * - Current minimal requirement
46     - 7.1
47     - 5.0
48     -
49   * - Feature
50     - GCC
51     - Clang
52     - Can be used in code
53   * - ``type_t &&``
54     - 4.3
55     - 2.9
56     - Yes (see notes)
57   * - ref qualifiers on methods
58     - 4.8.1
59     - 2.9
60     - Yes
61   * - default member - initializers (except for bit-fields)
62     - 4.7
63     - 3.0
64     - Yes
65   * - default member - initializers (for bit-fields)
66     - 8
67     - 6
68     - **No**
69   * - variadic templates
70     - 4.3
71     - 2.9
72     - Yes
73   * - Initializer lists
74     - 4.4
75     - 3.1
76     - Yes
77   * - ``static_assert``
78     - 4.3
79     - 2.9
80     - Yes
81   * - ``auto``
82     - 4.4
83     - 2.9
84     - Yes
85   * - lambdas
86     - 4.5
87     - 3.1
88     - Yes
89   * - ``decltype``
90     - 4.3
91     - 2.9
92     - Yes
93   * - ``Foo<Bar<T>>``
94     - 4.3
95     - 2.9
96     - Yes
97   * - ``auto func() -> int``
98     - 4.4
99     - 3.1
100     - Yes
101   * - Templated aliasing
102     - 4.7
103     - 3.0
104     - Yes
105   * - ``nullptr``
106     - 4.6
107     - 3.0
108     - Yes
109   * - ``enum foo : int16_t`` {};
110     - 4.4
111     - 2.9
112     - Yes
113   * - ``enum class foo {}``;
114     - 4.4
115     - 2.9
116     - Yes
117   * - ``enum foo;``
118     - 4.6
119     - 3.1
120     - Yes
121   * - ``[[attributes]]``
122     - 4.8
123     - 3.3
124     - **No** (see notes)
125   * - ``constexpr``
126     - 4.6
127     - 3.1
128     - Yes
129   * - ``alignas``
130     - 4.8
131     - 3.3
132     - Yes
133   * - ``alignof``
134     - 4.8
135     - 3.3
136     - Yes, but see notes ; only clang 3.6 claims as_feature(cxx_alignof)
137   * - Delegated constructors
138     - 4.7
139     - 3.0
140     - Yes
141   * - Inherited constructors
142     - 4.8
143     - 3.3
144     - Yes
145   * - ``explicit operator bool()``
146     - 4.5
147     - 3.0
148     - Yes
149   * - ``char16_t/u"string"``
150     - 4.4
151     - 3.0
152     - Yes
153   * - ``R"(string)"``
154     - 4.5
155     - 3.0
156     - Yes
157   * - ``operator""()``
158     - 4.7
159     - 3.1
160     - Yes
161   * - ``=delete``
162     - 4.4
163     - 2.9
164     - Yes
165   * - ``=default``
166     - 4.4
167     - 3.0
168     - Yes
169   * - unrestricted unions
170     - 4.6
171     - 3.1
172     - Yes
173   * - ``for (auto x : vec)`` (`be careful about the type of the iterator <https://stackoverflow.com/questions/15176104/c11-range-based-loop-get-item-by-value-or-reference-to-const>`__)
174     - 4.6
175     - 3.0
176     - Yes
177   * - ``override``/``final``
178     - 4.7
179     - 3.0
180     - Yes
181   * - ``thread_local``
182     - 4.8
183     - 3.3
184     - **No** (see notes)
185   * - function template default arguments
186     - 4.3
187     - 2.9
188     - Yes
189   * - local structs as template parameters
190     - 4.5
191     - 2.9
192     - Yes
193   * - extended friend declarations
194     - 4.7
195     - 2.9
196     - Yes
197   * - ``0b100`` (C++14)
198     - 4.9
199     - 2.9
200     - Yes
201   * - `Tweaks to some C++ contextual conversions` (C++14)
202     - 4.9
203     - 3.4
204     - Yes
205   * - Return type deduction (C++14)
206     - 4.9
207     - 3.4
208     - Yes (but only in template code when you would have used ``decltype (complex-expression)``)
209   * - Generic lambdas (C++14)
210     - 4.9
211     - 3.4
212     - Yes
213   * - Initialized lambda captures (C++14)
214     - 4.9
215     - 3.4
216     - Yes
217   * - Digit separator (C++14)
218     - 4.9
219     - 3.4
220     - Yes
221   * - Variable templates (C++14)
222     - 5.0
223     - 3.4
224     - Yes
225   * - Relaxed constexpr (C++14)
226     - 5.0
227     - 3.4
228     - Yes
229   * - Aggregate member initialization (C++14)
230     - 5.0
231     - 3.3
232     - Yes
233   * - Clarifying memory allocation (C++14)
234     - 5.0
235     - 3.4
236     - Yes
237   * - [[deprecated]] attribute (C++14)
238     - 4.9
239     - 3.4
240     - **No** (see notes)
241   * - Sized deallocation (C++14)
242     - 5.0
243     - 3.4
244     - **No** (see notes)
245   * - Concepts (Concepts TS)
246     - 6.0
247     - —
248     - **No**
249   * - Inline variables (C++17)
250     - 7.0
251     - 3.9
252     - **No** (clang 5 has bugs with inline variables)
253   * - constexpr_if (C++17)
254     - 7.0
255     - 3.9
256     - Yes
257   * - constexpr lambdas (C++17)
258     - —
259     - —
260     - **No**
261   * - Structured bindings (C++17)
262     - 7.0
263     - 4.0
264     - Yes
265   * - Separated declaration and condition in ``if``, ``switch`` (C++17)
266     - 7.0
267     - 3.9
268     - Yes
269   * - `Fold expressions <https://en.cppreference.com/w/cpp/language/fold>`__ (C++17)
270     - 6.0
271     - 3.9
272     - Yes
273   * - [[fallthrough]],  [[maybe_unused]], [[nodiscard]] (C++17)
274     - 7.0
275     - 3.9
276     - Yes
277   * - Aligned allocation/deallocation (C++17)
278     - 7.0
279     - 4.0
280     - **No** (see notes)
281   * - #pragma once
282     - 3.4
283     - Yes
284     - **Not** until we `normalize headers <https://groups.google.com/d/msg/mozilla.dev.platform/PgDjWw3xp8k/eqCFlP4Kz1MJ>`__
285   * - `Source code information capture <https://en.cppreference.com/w/cpp/experimental/lib_extensions_2#Source_code_information_capture>`__
286     - 8.0
287     - —
288     - **No**
289
290Sources
291~~~~~~~
292
293* GCC: https://gcc.gnu.org/projects/cxx-status.html
294* Clang: https://clang.llvm.org/cxx_status.html
295
296Notes
297~~~~~
298
299rvalue references: Implicit move method generation cannot be used.
300
301Attributes: Several common attributes are defined in
302`mozilla/Attributes.h <https://searchfox.org/mozilla-central/source/mfbt/Attributes.h>`__
303or nscore.h.
304
305Alignment: Some alignment utilities are defined in
306`mozilla/Alignment.h <https://searchfox.org/mozilla-central/source/mfbt/Alignment.h>`__.
307/!\\ MOZ_ALIGNOF and alignof don't have the same semantics. Be careful
308of what you expect from them.
309
310``[[deprecated]]``: If we have deprecated code, we should be removing it
311rather than marking it as such. Marking things as ``[[deprecated]]``
312also means the compiler will warn if you use the deprecated API, which
313turns into a fatal error in our automation builds, which is not helpful.
314
315Sized deallocation: Our compilers all support this (custom flags are
316required for GCC and Clang), but turning it on breaks some classes'
317``operator new`` methods, and `some
318work <https://bugzilla.mozilla.org/show_bug.cgi?id=1250998>`__ would
319need to be done to make it an efficiency win with our custom memory
320allocator.
321
322Aligned allocation/deallocation: Our custom memory allocator doesn't
323have support for these functions.
324
325Thread locals: ``thread_local`` is not supported on Android.
326
327
328C++ and Mozilla standard libraries
329----------------------------------
330
331The Mozilla codebase contains within it several subprojects which follow
332different rules for which libraries can and can't be used it. The rules
333listed here apply to normal platform code, and assume unrestricted
334usability of MFBT or XPCOM APIs.
335
336.. warning::
337
338   The rest of this section is a draft for expository and exploratory
339   purposes. Do not trust the information listed here.
340
341What follows is a list of standard library components provided by
342Mozilla or the C++ standard. If an API is not listed here, then it is
343not permissible to use it in Mozilla code. Deprecated APIs are not
344listed here. In general, prefer Mozilla variants of data structures to
345standard C++ ones, even when permitted to use the latter, since Mozilla
346variants tend to have features not found in the standard library (e.g.,
347memory size tracking) or have more controllable performance
348characteristics.
349
350A list of approved standard library headers is maintained in
351`config/stl-headers.mozbuild <https://searchfox.org/mozilla-central/source/config/stl-headers.mozbuild>`__.
352
353
354Data structures
355~~~~~~~~~~~~~~~
356
357.. list-table::
358   :widths: 25 25 25 25
359   :header-rows: 1
360
361   * - Name
362     - Header
363     - STL equivalent
364     - Notes
365   * - ``nsAutoTArray``
366     - ``nsTArray.h``
367     -
368     - Like ``nsTArray``, but will store a small amount as stack storage
369   * - ``nsAutoTObserverArray``
370     - ``nsTObserverArray.h``
371     -
372     - Like ``nsTObserverArray``, but will store a small amount as stack storage
373   * - ``mozilla::BloomFilter``
374     - ``mozilla/BloomFilter.h``
375     -
376     - Probabilistic set membership (see `Wikipedia <https://en.wikipedia.org/wiki/Bloom_filter#Counting_filters>`__)
377   * - ``nsClassHashtable``
378     - ``nsClassHashtable.h``
379     -
380     - Adaptation of nsTHashtable, see `XPCOM hashtable guide <https://developer.mozilla.org/docs/Mozilla/Tech/XPCOM/Guide/Hashtables>`__
381   * - ``nsCOMArray``
382     - ``nsCOMArray.h``
383     -
384     - Like ``nsTArray<nsCOMPtr<T>>``
385   * - ``nsDataHashtable``
386     - ``nsClassHashtable.h``
387     - ``std::unordered_map``
388     - Adaptation of ``nsTHashtable``, see `XPCOM hashtable guide <https://developer.mozilla.org/docs/Mozilla/Tech/XPCOM/Guide/Hashtables>`__
389   * - ``nsDeque``
390     - ``nsDeque.h``
391     - ``std::deque<void *>``
392     -
393   * - ``mozilla::EnumSet``
394     - ``mozilla/EnumSet.h``
395     -
396     - Like ``std::set``, but for enum classes.
397   * - ``mozilla::Hash{Map,Set}``
398     - `mozilla/HashTable.h <https://searchfox.org/mozilla-central/source/mfbt/HashTable.h>`__
399     - ``std::unordered_{map,set}``
400     - A general purpose hash map and hash set.
401   * - ``nsInterfaceHashtable``
402     - ``nsInterfaceHashtable.h``
403     - ``std::unordered_map``
404     - Adaptation of ``nsTHashtable``, see `XPCOM hashtable guide <https://developer.mozilla.org/docs/Mozilla/Tech/XPCOM/Guide/Hashtables>`__
405   * - ``mozilla::LinkedList``
406     - ``mozilla/LinkedList.h``
407     - ``std::list``
408     - Doubly-linked list
409   * - ``nsRef PtrHashtable``
410     - ``nsRefPtrHashtable.h``
411     - ``std::unordered_map``
412     - Adaptation of ``nsTHashtable``, see `XPCOM hashtable guide <https://developer.mozilla.org/docs/Mozilla/Tech/XPCOM/Guide/Hashtables>`__
413   * - ``mozilla::SegmentedVector``
414     - ``mozilla/SegmentedVector.h``
415     - ``std::deque`` w/o O(1) pop_front
416     - Doubly-linked list of vector elements
417   * - ``mozilla::SplayTree``
418     - ``mozilla/SplayTree.h``
419     -
420     - Quick access to recently-accessed elements (see `Wikipedia <https://en.wikipedia.org/wiki/Splay_tree>`__)
421   * - ``nsTArray``
422     - ``nsTArray.h``
423     - ``std::vector``
424     -
425   * - ``nsTHashtable``
426     - ``nsTHashtable.h``
427     - ``std::unordered_{map,set}``
428     - See `XPCOM hashtable guide <https://developer.mozilla.org/docs/Mozilla/Tech/XPCOM/Guide/Hashtables>`__,  you probably want a subclass
429   * - ``nsTObserverArray``
430     - ``nsTObserverArray.h``
431     -
432     - Like ``nsTArray``, but iteration is stable even through mutation
433   * - ``nsTPriorityQueue``
434     - ``nsTPriorityQueue.h``
435     - ``std::priority_queue``
436     - Unlike the STL class, not a container adapter
437   * - ``mozilla::Vector``
438     - ``mozilla/Vector.h``
439     - ``std::vector``
440     -
441   * - ``mozilla::Buffer``
442     - ``mozilla/Buffer.h``
443     -
444     - Unlike ``Array``, has a run-time variable length. Unlike ``Vector``, does not have capacity and growth mechanism. Unlike  ``Span``, owns  its buffer.
445
446
447Safety utilities
448~~~~~~~~~~~~~~~~
449
450.. list-table::
451   :widths: 25 25 25 25
452   :header-rows: 1
453
454   * - Name
455     - Header
456     - STL equivalent
457     - Notes
458   * - ``mozilla::Array``
459     - ``mfbt/Array.h``
460     -
461     - safe array index
462   * - ``mozilla::AssertedCast``
463     - ``mfbt/Casting.h``
464     -
465     - casts
466   * - ``mozilla::CheckedInt``
467     - ``mfbt/CheckedInt.h``
468     -
469     - avoids overflow
470   * - ``nsCOMPtr``
471     - ``xpcom/base/nsCOMPtr.h``
472     - ``std::shared_ptr``
473     -
474   * - ``mozilla::EnumeratedArray``
475     - ``mfbt/EnumeratedArray.h``
476     - ``mozilla::Array``
477     -
478   * - ``mozilla::Maybe``
479     - ``mfbt/Maybe.h``
480     - ``std::optional``
481     -
482   * - ``mozilla::RangedPtr``
483     - ``mfbt/RangedPtr.h``
484     -
485     - like ``mozilla::Span`` but with two pointers instead of pointer and length
486   * - ``mozilla::RefPtr``
487     - ``mfbt/RefPtr.h``
488     - ``std::shared_ptr``
489     -
490   * - ``mozilla::Span``
491     - ``mozilla/Span.h``
492     - ``gsl::span``, ``absl::Span``, ``std::string_view``, ``std::u16string_view``
493     - Rust's slice concept for C++ (without borrow checking)
494   * - ``StaticRefPtr``
495     - ``xpcom/base/StaticPtr.h``
496     -
497     - ``nsRefPtr`` w/o static constructor
498   * - ``mozilla::UniquePtr``
499     - ``mfbt/UniquePtr.h``
500     - ``std::unique_ptr``
501     -
502   * - ``mozilla::WeakPtr``
503     - ``mfbt/WeakPtr.h``
504     - ``std::weak_ptr``
505     -
506   * - ``nsWeakPtr``
507     - ``xpcom/base/nsWeakPtr.h``
508     - ``std::weak_ptr``
509     -
510
511
512Strings
513~~~~~~~
514
515See the `Mozilla internal string
516guide <https://developer.mozilla.org/docs/Mozilla/Tech/XPCOM/Guide/Internal_strings>`__ for
517usage of ``nsAString`` (our copy-on-write replacement for
518``std::u16string``) and ``nsACString`` (our copy-on-write replacement
519for ``std::string``).
520
521Be sure not to introduce further uses of ``std::wstring``, which is not
522portable! (Some uses exist in the IPC code.)
523
524
525Algorithms
526~~~~~~~~~~
527
528.. list-table::
529   :widths: 25 25
530
531   * - ``mozilla::BinarySearch``
532     - ``mfbt/BinarySearch.h``
533   * - ``mozilla::BitwiseCast``
534     - ``mfbt/Casting.h`` (strict aliasing-safe cast)
535   * - ``mozilla/MathAlgorithms.h``
536     - (rotate, ctlz, popcount, gcd, abs, lcm)
537   * - ``mozilla::RollingMean``
538     - ``mfbt/RollingMean.h`` ()
539
540
541Concurrency
542~~~~~~~~~~~
543
544.. list-table::
545   :widths: 25 25 25 25
546   :header-rows: 1
547
548   * - Name
549     - Header
550     - STL/boost equivalent
551     - Notes
552   * - ``mozilla::Atomic``
553     - mfbt/Atomic.h
554     - ``std::atomic``
555     -
556   * - ``mozilla::CondVar``
557     - xpcom/threads/CondVar.h
558     - ``std::condition_variable``
559     -
560   * - ``mozilla::DataMutex``
561     - xpcom/threads/DataMutex.h
562     - ``boost::synchronized_value``
563     -
564   * - ``mozilla::Monitor``
565     - xpcom/threads/Monitor.h
566     -
567     -
568   * - ``mozilla::Mutex``
569     - xpcom/threads/Mutex.h
570     - ``std::mutex``
571     -
572   * - ``mozilla::ReentrantMonitor``
573     - xpcom/threads/ReentrantMonitor.h
574     -
575     -
576   * - ``mozilla::StaticMutex``
577     - xpcom/base/StaticMutex.h
578     - ``std::mutex``
579     - Mutex that can (and in fact, must) be used as a global/static variable.
580
581
582Miscellaneous
583~~~~~~~~~~~~~
584
585.. list-table::
586   :widths: 25 25 25 25
587   :header-rows: 1
588
589   * - Name
590     - Header
591     - STL/boost equivalent
592     - Notes
593   * - ``mozilla::AlignedStorage``
594     - mfbt/Alignment.h
595     - ``std::aligned_storage``
596     -
597   * - ``mozilla::MaybeOneOf``
598     - mfbt/MaybeOneOf.h
599     - ``std::optional<std::variant<T1, T2>>``
600     - ~ ``mozilla::Maybe<union {T1, T2}>``
601   * - ``mozilla::Pair``
602     - mfbt/Pair.h
603     - ``std::tuple<T1, T2>``
604     - minimal space!
605   * - ``mozilla::TimeStamp``
606     - xpcom/ds/TimeStamp.h
607     - ``std::chrono::time_point``
608     -
609   * -
610     - mozilla/TypeTraits.h
611     - ``<type_traits>``
612     -
613   * -
614     - mozilla/PodOperations.h
615     -
616     - C++ versions of ``memset``, ``memcpy``, etc.
617   * -
618     - mozilla/ArrayUtils.h
619     -
620     -
621   * -
622     - mozilla/Compression.h
623     -
624     -
625   * -
626     - mozilla/Endian.h
627     -
628     -
629   * -
630     - mozilla/FloatingPoint.h
631     -
632     -
633   * -
634     - mozilla/HashFunctions.h
635     - ``std::hash``
636     -
637   * -
638     - mozilla/Move.h
639     - ``std::move``, ``std::swap``, ``std::forward``
640     -
641
642
643Mozilla data structures and standard C++ ranges and iterators
644~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
645
646Some Mozilla-defined data structures provide STL-style
647`iterators <https://en.cppreference.com/w/cpp/named_req/Iterator>`__ and
648are usable in `range-based for
649loops <https://en.cppreference.com/w/cpp/language/range-for>`__ as well
650as STL `algorithms <https://en.cppreference.com/w/cpp/algorithm>`__.
651
652Currently, these include:
653
654.. list-table::
655   :widths: 16 16 16 16 16
656   :header-rows: 1
657
658   * - Name
659     - Header
660     - Bug(s)
661     - Iterator category
662     - Notes
663   * - ``nsTArray``
664     - ``xpcom/ds/n sTArray.h``
665     - `1126552 <https://bugzilla.mozilla.org/show_bug.cgi?id=1126552>`__
666     - Random-access
667     - Also reverse-iterable. Also supports remove-erase pattern via RemoveElementsAt method. Also supports back-inserting output iterators via ``MakeBackInserter`` function.
668   * - ``nsBaseHashtable`` and subclasses: ``nsClassHashtable`` ``nsDataHashtable`` ``nsInterfaceHashtable`` ``nsJSThingHashtable`` ``nsRefPtrHashtable``
669     - ``xpcom/ds/nsBaseHashtable.h`` ``xpcom/ds/nsClassHashtable.h`` ``xpcom/ds/nsDataHashtable.h`` ``xpcom/ds/nsInterfaceHashtable.h`` ``xpcom/ds/nsJSThingHashtable.h`` ``xpcom/ds/nsRefPtrHashtable.h``
670     - `1575479 <https://bugzilla.mozilla.org/show_bug.cgi?id=1575479>`__
671     - Forward
672     -
673   * - ``nsCOMArray``
674     - ``xpcom/ds/nsCOMArray.h``
675     - `1342303 <https://bugzilla.mozilla.org/show_bug.cgi?id=1342303>`__
676     - Random-access
677     - Also reverse-iterable.
678   * - ``Array`` ``EnumerationArray`` ``RangedArray``
679     - ``mfbt/Array.h`` ``mfbt/EnumerationArray.h`` ``mfbt/RangedArray.h``
680     - `1216041 <https://bugzilla.mozilla.org/show_bug.cgi?id=1216041>`__
681     - Random-access
682     - Also reverse-iterable.
683   * - ``Buffer``
684     - ``mfbt/Buffer.h``
685     - `1512155 <https://bugzilla.mozilla.org/show_bug.cgi?id=1512155>`__
686     - Random-access
687     - Also reverse-iterable.
688   * - ``DoublyLinkedList``
689     - ``mfbt/DoublyLinkedList.h``
690     - `1277725 <https://bugzilla.mozilla.org/show_bug.cgi?id=1277725>`__
691     - Forward
692     -
693   * - ``EnumeratedRange``
694     - ``mfbt/EnumeratedRange.h``
695     - `1142999 <https://bugzilla.mozilla.org/show_bug.cgi?id=1142999>`__
696     - *Missing*
697     - Also reverse-iterable.
698   * - ``IntegerRange``
699     - ``mfbt/IntegerRange.h``
700     - `1126701 <https://bugzilla.mozilla.org/show_bug.cgi?id=1126701>`__
701     - *Missing*
702     - Also reverse-iterable.
703   * - ``SmallPointerArray``
704     - ``mfbt/SmallPointerArray.h``
705     - `1331718 <https://bugzilla.mozilla.org/show_bug.cgi?id=1331718>`__
706     - Random-access
707     -
708   * - ``Span``
709     - ``mfbt/Span.h``
710     - `1295611 <https://bugzilla.mozilla.org/show_bug.cgi?id=1295611>`__
711     - Random-access
712     - Also reverse-iterable.
713
714Note that if the iterator category is stated as "missing", the type is
715probably only usable in range-based for. This is most likely just an
716omission, which could be easily fixed.
717
718Useful in this context are also the class template ``IteratorRange``
719(which can be used to construct a range from any pair of iterators) and
720function template ``Reversed`` (which can be used to reverse any range),
721both defined in ``mfbt/ReverseIterator.h``
722
723
724Further C++ rules
725-----------------
726
727
728Don't use static constructors
729~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
730
731(You probably shouldn't be using global variables to begin with. Quite
732apart from the weighty software-engineering arguments against them,
733globals affect startup time! But sometimes we have to do ugly things.)
734
735Non-portable example:
736
737.. code-block:: c++
738
739   FooBarClass static_object(87, 92);
740
741   void
742   bar()
743   {
744     if (static_object.count > 15) {
745        ...
746     }
747   }
748
749Once upon a time, there were compiler bugs that could result in
750constructors not being called for global objects. Those bugs are
751probably long gone by now, but even with the feature working correctly,
752there are so many problems with correctly ordering C++ constructors that
753it's easier to just have an init function:
754
755.. code-block:: c++
756
757   static FooBarClass* static_object;
758
759   FooBarClass*
760   getStaticObject()
761   {
762     if (!static_object)
763       static_object =
764         new FooBarClass(87, 92);
765     return static_object;
766   }
767
768   void
769   bar()
770   {
771     if (getStaticObject()->count > 15) {
772       ...
773     }
774   }
775
776
777Don't use exceptions
778~~~~~~~~~~~~~~~~~~~~
779
780See the introduction to the "C++ language features" section at the start
781of this document.
782
783
784Don't use Run-time Type Information
785~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
786
787See the introduction to the "C++ language features" section at the start
788of this document.
789
790If you need runtime typing, you can achieve a similar result by adding a
791``classOf()`` virtual member function to the base class of your
792hierarchy and overriding that member function in each subclass. If
793``classOf()`` returns a unique value for each class in the hierarchy,
794you'll be able to do type comparisons at runtime.
795
796
797Don't use the C++ standard library (including iostream and locale)
798~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
799
800See the section "C++ and Mozilla standard libraries".
801
802
803Use C++ lambdas, but with care
804~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
805
806C++ lambdas are supported across all our compilers now. Rejoice! We
807recommend explicitly listing out the variables that you capture in the
808lambda, both for documentation purposes, and to double-check that you're
809only capturing what you expect to capture.
810
811
812Use namespaces
813~~~~~~~~~~~~~~
814
815Namespaces may be used according to the style guidelines in :ref:`C++ Coding style`.
816
817
818Don't mix varargs and inlines
819~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
820
821What? Why are you using varargs to begin with?! Stop that at once!
822
823
824Make header files compatible with C and C++
825~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
826
827Non-portable example:
828
829.. code-block:: c++
830
831   /*oldCheader.h*/
832   int existingCfunction(char*);
833   int anotherExistingCfunction(char*);
834
835   /* oldCfile.c */
836   #include "oldCheader.h"
837   ...
838
839   // new file.cpp
840   extern "C" {
841   #include "oldCheader.h"
842   };
843   ...
844
845If you make new header files with exposed C interfaces, make the header
846files work correctly when they are included by both C and C++ files.
847
848(If you need to include a C header in new C++ files, that should just
849work. If not, it's the C header maintainer's fault, so fix the header if
850you can, and if not, whatever hack you come up with will probably be
851fine.)
852
853Portable example:
854
855.. code-block:: c++
856
857   /* oldCheader.h*/
858   PR_BEGIN_EXTERN_C
859   int existingCfunction(char*);
860   int anotherExistingCfunction(char*);
861   PR_END_EXTERN_C
862
863   /* oldCfile.c */
864   #include "oldCheader.h"
865   ...
866
867   // new file.cpp
868   #include "oldCheader.h"
869   ...
870
871There are number of reasons for doing this, other than just good style.
872For one thing, you are making life easier for everyone else, doing the
873work in one common place (the header file) instead of all the C++ files
874that include it. Also, by making the C header safe for C++, you document
875that "hey, this file is now being included in C++". That's a good thing.
876You also avoid a big portability nightmare that is nasty to fix...
877
878
879Use override on subclass virtual member functions
880~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
881
882The ``override`` keyword is supported in C++11 and in all our supported
883compilers, and it catches bugs.
884
885
886Always declare a copy constructor and assignment operator
887~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
888
889Many classes shouldn't be copied or assigned. If you're writing one of
890these, the way to enforce your policy is to declare a deleted copy
891constructor as private and not supply a definition. While you're at it,
892do the same for the assignment operator used for assignment of objects
893of the same class. Example:
894
895.. code-block:: c++
896
897   class Foo {
898     ...
899     private:
900       Foo(const Foo& x) = delete;
901       Foo& operator=(const Foo& x) = delete;
902   };
903
904Any code that implicitly calls the copy constructor will hit a
905compile-time error. That way nothing happens in the dark. When a user's
906code won't compile, they'll see that they were passing by value, when
907they meant to pass by reference (oops).
908
909
910Be careful of overloaded methods with like signatures
911~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
912
913It's best to avoid overloading methods when the type signature of the
914methods differs only by one "abstract" type (e.g. ``PR_Int32`` or
915``int32``). What you will find as you move that code to different
916platforms, is suddenly on the Foo2000 compiler your overloaded methods
917will have the same type-signature.
918
919
920Type scalar constants to avoid unexpected ambiguities
921~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
922
923Non-portable code:
924
925.. code-block:: c++
926
927   class FooClass {
928     // having such similar signatures
929     // is a bad idea in the first place.
930     void doit(long);
931     void doit(short);
932   };
933
934   void
935   B::foo(FooClass* xyz)
936   {
937     xyz->doit(45);
938   }
939
940Be sure to type your scalar constants, e.g., ``uint32_t(10)`` or
941``10L``. Otherwise, you can produce ambiguous function calls which
942potentially could resolve to multiple methods, particularly if you
943haven't followed (2) above. Not all of the compilers will flag ambiguous
944method calls.
945
946Portable code:
947
948.. code-block:: c++
949
950   class FooClass {
951     // having such similar signatures
952     // is a bad idea in the first place.
953     void doit(long);
954     void doit(short);
955   };
956
957   void
958   B::foo(FooClass* xyz)
959   {
960     xyz->doit(45L);
961   }
962
963
964Use nsCOMPtr in XPCOM code
965~~~~~~~~~~~~~~~~~~~~~~~~~~
966
967See the ``nsCOMPtr`` `User
968Manual <https://developer.mozilla.org/en-US/docs/Using_nsCOMPtr>`__ for
969usage details.
970
971
972Don't use identifiers that start with an underscore
973~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
974
975This rule occasionally surprises people who've been hacking C++ for
976decades. But it comes directly from the C++ standard!
977
978According to the C++ Standard, 17.4.3.1.2 Global Names
979[lib.global.names], paragraph 1:
980
981Certain sets of names and function signatures are always reserved to the
982implementation:
983
984-  Each name that contains a double underscore (__) or begins with an
985   underscore followed by an uppercase letter (2.11) is reserved to the
986   implementation for any use.
987-  **Each name that begins with an underscore is reserved to the
988   implementation** for use as a name in the global namespace.
989
990
991Stuff that is good to do for C or C++
992-------------------------------------
993
994
995Avoid conditional #includes when possible
996~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
997
998Don't write an ``#include`` inside an ``#ifdef`` if you could instead
999put it outside. Unconditional includes are better because they make the
1000compilation more similar across all platforms and configurations, so
1001you're less likely to cause stupid compiler errors on someone else's
1002favorite platform that you never use.
1003
1004Bad code example:
1005
1006.. code-block:: c++
1007
1008   #ifdef MOZ_ENABLE_JPEG_FOUR_BILLION
1009   #include <stdlib.h>   // <--- don't do this
1010   #include "jpeg4e9.h"  // <--- only do this if the header really might not be there
1011   #endif
1012
1013Of course when you're including different system files for different
1014machines, you don't have much choice. That's different.
1015
1016
1017Every .cpp source file should have a unique name
1018~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1019
1020Every object file linked into libxul needs to have a unique name. Avoid
1021generic names like nsModule.cpp and instead use nsPlacesModule.cpp.
1022
1023
1024Turn on warnings for your compiler, and then write warning free code
1025~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1026
1027What generates a warning on one platform will generate errors on
1028another. Turn warnings on. Write warning-free code. It's good for you.
1029Treat warnings as errors by adding
1030``ac_add_options --enable-warnings-as-errors`` to your mozconfig file.
1031
1032
1033Use the same type for all bitfields in a ``struct`` or ``class``
1034~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1035
1036Some compilers do not pack the bits when different bitfields are given
1037different types. For example, the following struct might have a size of
10388 bytes, even though it would fit in 1:
1039
1040.. code-block:: c++
1041
1042   struct {
1043     char ch: 1;
1044     int i: 1;
1045   };
1046
1047
1048Don't use an enum type for a bitfield
1049~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1050
1051The classic example of this is using ``PRBool`` for a boolean bitfield.
1052Don't do that. ``PRBool`` is a signed integer type, so the bitfield's
1053value when set will be ``-1`` instead of ``+1``, which---I know,
1054*crazy*, right? The things C++ hackers used to have to put up with...
1055
1056You shouldn't be using ``PRBool`` anyway. Use ``bool``. Bitfields of
1057type ``bool`` are fine.
1058
1059Enums are signed on some platforms (in some configurations) and unsigned
1060on others and therefore unsuitable for writing portable code when every
1061bit counts, even if they happen to work on your system.
1062