forked from mirrors/gecko-dev
		
	 df7f09424c
			
		
	
	
		df7f09424c
		
	
	
	
	
		
			
			I replaced the color by bold on "No". It seems we can't have color in cells with rst :/ Differential Revision: https://phabricator.services.mozilla.com/D77444
		
			
				
	
	
		
			1065 lines
		
	
	
	
		
			29 KiB
		
	
	
	
		
			ReStructuredText
		
	
	
	
	
	
			
		
		
	
	
			1065 lines
		
	
	
	
		
			29 KiB
		
	
	
	
		
			ReStructuredText
		
	
	
	
	
	
| Using C++ in Mozilla code
 | |
| =========================
 | |
| 
 | |
| C++ language features
 | |
| ---------------------
 | |
| 
 | |
| Mozilla code only uses a subset of C++. Runtime type information (RTTI)
 | |
| is disabled, as it tends to cause a very large increase in codesize.
 | |
| This means that ``dynamic_cast``, ``typeid()`` and ``<typeinfo>`` cannot
 | |
| be used in Mozilla code. Also disabled are exceptions; do not use
 | |
| ``try``/``catch`` or throw any exceptions. Libraries that throw
 | |
| exceptions may be used if you are willing to have the throw instead be
 | |
| treated as an abort.
 | |
| 
 | |
| On the side of extending C++, we compile with ``-fno-strict-aliasing``.
 | |
| This means that when reinterpreting a pointer as a differently-typed
 | |
| pointer, you don't need to adhere to the "effective type" (of the
 | |
| pointee) rule from the standard (aka. "the strict aliasing rule") when
 | |
| dereferencing the reinterpreted pointer. You still need make sure that
 | |
| you don't violate alignment requirements and need to make sure that the
 | |
| data at the memory location pointed to forms a valid value when
 | |
| interpreted according to the type of the pointer when dereferencing the
 | |
| pointer for reading. Likewise, if you write by dereferencing the
 | |
| reinterpreted pointer and the originally-typed pointer might still be
 | |
| dereferenced for reading, you need to make sure that the values you
 | |
| write are valid according to the original type. This value validity
 | |
| issue is moot for e.g. primitive integers for which all bit patterns of
 | |
| their size are valid values.
 | |
| 
 | |
| -  As of Mozilla 59, C++14 mode is required to build Mozilla.
 | |
| -  As of Mozilla 67, MSVC can no longer be used to build Mozilla.
 | |
| -  As of Mozilla 73, C++17 mode is required to build Mozilla.
 | |
| 
 | |
| This means that C++17 can be used where supported on all platforms. The
 | |
| list of acceptable features is given below:
 | |
| 
 | |
| .. list-table::
 | |
|    :widths: 25 25 25 25
 | |
|    :header-rows: 3
 | |
| 
 | |
|    * - 
 | |
|      - GCC
 | |
|      - Clang
 | |
|      -
 | |
|    * - Current minimal requirement
 | |
|      - 7.1
 | |
|      - 5.0
 | |
|      -
 | |
|    * - Feature
 | |
|      - GCC
 | |
|      - Clang
 | |
|      - Can be used in code
 | |
|    * - ``type_t &&``
 | |
|      - 4.3
 | |
|      - 2.9
 | |
|      - Yes (see notes)
 | |
|    * - ref qualifiers on methods
 | |
|      - 4.8.1
 | |
|      - 2.9
 | |
|      - Yes
 | |
|    * - default member - initializers (except for bit-fields)
 | |
|      - 4.7
 | |
|      - 3.0
 | |
|      - Yes
 | |
|    * - default member - initializers (for bit-fields)
 | |
|      - 8
 | |
|      - 6
 | |
|      - **No**
 | |
|    * - variadic templates
 | |
|      - 4.3
 | |
|      - 2.9
 | |
|      - Yes
 | |
|    * - Initializer lists
 | |
|      - 4.4
 | |
|      - 3.1
 | |
|      - Yes
 | |
|    * - ``static_assert``
 | |
|      - 4.3
 | |
|      - 2.9
 | |
|      - Yes
 | |
|    * - ``auto``
 | |
|      - 4.4
 | |
|      - 2.9
 | |
|      - Yes
 | |
|    * - lambdas
 | |
|      - 4.5
 | |
|      - 3.1
 | |
|      - Yes
 | |
|    * - ``decltype``
 | |
|      - 4.3
 | |
|      - 2.9
 | |
|      - Yes
 | |
|    * - ``Foo<Bar<T>>``
 | |
|      - 4.3
 | |
|      - 2.9
 | |
|      - Yes
 | |
|    * - ``auto func() -> int``
 | |
|      - 4.4
 | |
|      - 3.1
 | |
|      - Yes
 | |
|    * - Templated aliasing
 | |
|      - 4.7
 | |
|      - 3.0
 | |
|      - Yes
 | |
|    * - ``nullptr``
 | |
|      - 4.6
 | |
|      - 3.0
 | |
|      - Yes
 | |
|    * - ``enum foo : int16_t`` {};
 | |
|      - 4.4
 | |
|      - 2.9
 | |
|      - Yes
 | |
|    * - ``enum class foo {}``;
 | |
|      - 4.4
 | |
|      - 2.9
 | |
|      - Yes
 | |
|    * - ``enum foo;``
 | |
|      - 4.6
 | |
|      - 3.1
 | |
|      - Yes
 | |
|    * - ``[[attributes]]``
 | |
|      - 4.8
 | |
|      - 3.3
 | |
|      - **No** (see notes)
 | |
|    * - ``constexpr``
 | |
|      - 4.6
 | |
|      - 3.1
 | |
|      - Yes
 | |
|    * - ``alignas``
 | |
|      - 4.8
 | |
|      - 3.3
 | |
|      - Yes
 | |
|    * - ``alignof``
 | |
|      - 4.8
 | |
|      - 3.3
 | |
|      - Yes, but see notes ; only clang 3.6 claims as_feature(cxx_alignof)
 | |
|    * - Delegated constructors
 | |
|      - 4.7
 | |
|      - 3.0
 | |
|      - Yes
 | |
|    * - Inherited constructors
 | |
|      - 4.8
 | |
|      - 3.3
 | |
|      - Yes
 | |
|    * - ``explicit operator bool()``
 | |
|      - 4.5
 | |
|      - 3.0
 | |
|      - Yes
 | |
|    * - ``char16_t/u"string"``
 | |
|      - 4.4
 | |
|      - 3.0
 | |
|      - Yes
 | |
|    * - ``R"(string)"``
 | |
|      - 4.5
 | |
|      - 3.0
 | |
|      - Yes
 | |
|    * - ``operator""()``
 | |
|      - 4.7
 | |
|      - 3.1
 | |
|      - Yes
 | |
|    * - ``=delete``
 | |
|      - 4.4
 | |
|      - 2.9
 | |
|      - Yes
 | |
|    * - ``=default``
 | |
|      - 4.4
 | |
|      - 3.0
 | |
|      - Yes
 | |
|    * - unrestricted unions
 | |
|      - 4.6
 | |
|      - 3.1
 | |
|      - Yes
 | |
|    * - ``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>`__)
 | |
|      - 4.6
 | |
|      - 3.0
 | |
|      - Yes
 | |
|    * - ``override``/``final``
 | |
|      - 4.7
 | |
|      - 3.0
 | |
|      - Yes
 | |
|    * - ``thread_local``
 | |
|      - 4.8
 | |
|      - 3.3
 | |
|      - **No** (see notes)
 | |
|    * - function template default arguments
 | |
|      - 4.3
 | |
|      - 2.9
 | |
|      - Yes
 | |
|    * - local structs as template parameters
 | |
|      - 4.5
 | |
|      - 2.9
 | |
|      - Yes
 | |
|    * - extended friend declarations
 | |
|      - 4.7
 | |
|      - 2.9
 | |
|      - Yes
 | |
|    * - ``0b100`` (C++14)
 | |
|      - 4.9
 | |
|      - 2.9
 | |
|      - Yes
 | |
|    * - `Tweaks to some C++ contextual conversions` (C++14)
 | |
|      - 4.9
 | |
|      - 3.4
 | |
|      - Yes
 | |
|    * - Return type deduction (C++14)
 | |
|      - 4.9
 | |
|      - 3.4
 | |
|      - Yes (but only in template code when you would have used ``decltype (complex-expression)``)
 | |
|    * - Generic lambdas (C++14)
 | |
|      - 4.9
 | |
|      - 3.4
 | |
|      - Yes
 | |
|    * - Initialized lambda captures (C++14)
 | |
|      - 4.9
 | |
|      - 3.4
 | |
|      - Yes
 | |
|    * - Digit separator (C++14)
 | |
|      - 4.9
 | |
|      - 3.4
 | |
|      - Yes
 | |
|    * - Variable templates (C++14)
 | |
|      - 5.0
 | |
|      - 3.4
 | |
|      - Yes
 | |
|    * - Relaxed constexpr (C++14)
 | |
|      - 5.0
 | |
|      - 3.4
 | |
|      - Yes
 | |
|    * - Aggregate member initialization (C++14)
 | |
|      - 5.0
 | |
|      - 3.3
 | |
|      - Yes
 | |
|    * - Clarifying memory allocation (C++14)
 | |
|      - 5.0
 | |
|      - 3.4
 | |
|      - Yes
 | |
|    * - [[deprecated]] attribute (C++14)
 | |
|      - 4.9
 | |
|      - 3.4
 | |
|      - **No** (see notes)
 | |
|    * - Sized deallocation (C++14)
 | |
|      - 5.0
 | |
|      - 3.4
 | |
|      - **No** (see notes)
 | |
|    * - Concepts (Concepts TS)
 | |
|      - 6.0
 | |
|      - —
 | |
|      - **No**
 | |
|    * - Inline variables (C++17)
 | |
|      - 7.0
 | |
|      - 3.9
 | |
|      - **No** (clang 5 has bugs with inline variables)
 | |
|    * - constexpr_if (C++17)
 | |
|      - 7.0
 | |
|      - 3.9
 | |
|      - Yes
 | |
|    * - constexpr lambdas (C++17)
 | |
|      - —
 | |
|      - —
 | |
|      - **No**
 | |
|    * - Structured bindings (C++17)
 | |
|      - 7.0
 | |
|      - 4.0
 | |
|      - Yes
 | |
|    * - Separated declaration and condition in ``if``, ``switch`` (C++17)
 | |
|      - 7.0
 | |
|      - 3.9
 | |
|      - Yes
 | |
|    * - `Fold expressions <https://en.cppreference.com/w/cpp/language/fold>`__ (C++17)
 | |
|      - 6.0
 | |
|      - 3.9
 | |
|      - Yes
 | |
|    * - [[fallthrough]],  [[maybe_unused]], [[nodiscard]] (C++17)
 | |
|      - 7.0
 | |
|      - 3.9
 | |
|      - Yes
 | |
|    * - Aligned allocation/deallocation (C++17)
 | |
|      - 7.0
 | |
|      - 4.0
 | |
|      - **No** (see notes)
 | |
|    * - #pragma once
 | |
|      - 3.4
 | |
|      - Yes
 | |
|      - **Not** until we `normalize headers <https://groups.google.com/d/msg/mozilla.dev.platform/PgDjWw3xp8k/eqCFlP4Kz1MJ>`__
 | |
|    * - `Source code information capture <https://en.cppreference.com/w/cpp/experimental/lib_extensions_2#Source_code_information_capture>`__
 | |
|      - 8.0
 | |
|      - —
 | |
|      - **No**
 | |
| 
 | |
| Sources
 | |
| ~~~~~~~
 | |
| 
 | |
| * GCC: https://gcc.gnu.org/projects/cxx-status.html
 | |
| * Clang: https://clang.llvm.org/cxx_status.html
 | |
| 
 | |
| Notes
 | |
| ~~~~~
 | |
| 
 | |
| rvalue references: Implicit move method generation cannot be used.
 | |
| 
 | |
| Attributes: Several common attributes are defined in
 | |
| `mozilla/Attributes.h <https://searchfox.org/mozilla-central/source/mfbt/Attributes.h>`__
 | |
| or nscore.h.
 | |
| 
 | |
| Alignment: Some alignment utilities are defined in
 | |
| `mozilla/Alignment.h <https://searchfox.org/mozilla-central/source/mfbt/Alignment.h>`__.
 | |
| /!\\ MOZ_ALIGNOF and alignof don't have the same semantics. Be careful
 | |
| of what you expect from them.
 | |
| 
 | |
| ``[[deprecated]]``: If we have deprecated code, we should be removing it
 | |
| rather than marking it as such. Marking things as ``[[deprecated]]``
 | |
| also means the compiler will warn if you use the deprecated API, which
 | |
| turns into a fatal error in our automation builds, which is not helpful.
 | |
| 
 | |
| Sized deallocation: Our compilers all support this (custom flags are
 | |
| required for GCC and Clang), but turning it on breaks some classes'
 | |
| ``operator new`` methods, and `some
 | |
| work <https://bugzilla.mozilla.org/show_bug.cgi?id=1250998>`__ would
 | |
| need to be done to make it an efficiency win with our custom memory
 | |
| allocator.
 | |
| 
 | |
| Aligned allocation/deallocation: Our custom memory allocator doesn't
 | |
| have support for these functions.
 | |
| 
 | |
| Thread locals: ``thread_local`` is not supported on Android.
 | |
| 
 | |
| 
 | |
| C++ and Mozilla standard libraries
 | |
| ----------------------------------
 | |
| 
 | |
| The Mozilla codebase contains within it several subprojects which follow
 | |
| different rules for which libraries can and can't be used it. The rules
 | |
| listed here apply to normal platform code, and assume unrestricted
 | |
| usability of MFBT or XPCOM APIs.
 | |
| 
 | |
| .. warning::
 | |
| 
 | |
|    The rest of this section is a draft for expository and exploratory
 | |
|    purposes. Do not trust the information listed here.
 | |
| 
 | |
| What follows is a list of standard library components provided by
 | |
| Mozilla or the C++ standard. If an API is not listed here, then it is
 | |
| not permissible to use it in Mozilla code. Deprecated APIs are not
 | |
| listed here. In general, prefer Mozilla variants of data structures to
 | |
| standard C++ ones, even when permitted to use the latter, since Mozilla
 | |
| variants tend to have features not found in the standard library (e.g.,
 | |
| memory size tracking) or have more controllable performance
 | |
| characteristics.
 | |
| 
 | |
| A list of approved standard library headers is maintained in
 | |
| `config/stl-headers.mozbuild <https://searchfox.org/mozilla-central/source/config/stl-headers.mozbuild>`__.
 | |
| 
 | |
| 
 | |
| Data structures
 | |
| ~~~~~~~~~~~~~~~
 | |
| 
 | |
| .. list-table::
 | |
|    :widths: 25 25 25 25
 | |
|    :header-rows: 1
 | |
| 
 | |
|    * - Name
 | |
|      - Header
 | |
|      - STL equivalent
 | |
|      - Notes
 | |
|    * - ``nsAutoTArray``
 | |
|      - ``nsTArray.h``
 | |
|      -
 | |
|      - Like ``nsTArray``, but will store a small amount as stack storage
 | |
|    * - ``nsAutoTObserverArray``
 | |
|      - ``nsTObserverArray.h``
 | |
|      -
 | |
|      - Like ``nsTObserverArray``, but will store a small amount as stack storage
 | |
|    * - ``mozilla::BloomFilter``
 | |
|      - ``mozilla/BloomFilter.h``
 | |
|      -
 | |
|      - Probabilistic set membership (see `Wikipedia <https://en.wikipedia.org/wiki/Bloom_filter#Counting_filters>`__)
 | |
|    * - ``nsClassHashtable``
 | |
|      - ``nsClassHashtable.h``
 | |
|      -
 | |
|      - Adaptation of nsTHashtable, see `XPCOM hashtable guide <https://developer.mozilla.org/docs/Mozilla/Tech/XPCOM/Guide/Hashtables>`__
 | |
|    * - ``nsCOMArray``
 | |
|      - ``nsCOMArray.h``
 | |
|      -
 | |
|      - Like ``nsTArray<nsCOMPtr<T>>``
 | |
|    * - ``nsDataHashtable``
 | |
|      - ``nsClassHashtable.h``
 | |
|      - ``std::unordered_map``
 | |
|      - Adaptation of ``nsTHashtable``, see `XPCOM hashtable guide <https://developer.mozilla.org/docs/Mozilla/Tech/XPCOM/Guide/Hashtables>`__
 | |
|    * - ``nsDeque``
 | |
|      - ``nsDeque.h``
 | |
|      - ``std::deque<void *>``
 | |
|      -
 | |
|    * - ``mozilla::EnumSet``
 | |
|      - ``mozilla/EnumSet.h``
 | |
|      -
 | |
|      - Like ``std::set``, but for enum classes.
 | |
|    * - ``mozilla::Hash{Map,Set}``
 | |
|      - `mozilla/HashTable.h <https://searchfox.org/mozilla-central/source/mfbt/HashTable.h>`__
 | |
|      - ``std::unordered_{map,set}``
 | |
|      - A general purpose hash map and hash set.
 | |
|    * - ``nsInterfaceHashtable``
 | |
|      - ``nsInterfaceHashtable.h``
 | |
|      - ``std::unordered_map``
 | |
|      - Adaptation of ``nsTHashtable``, see `XPCOM hashtable guide <https://developer.mozilla.org/docs/Mozilla/Tech/XPCOM/Guide/Hashtables>`__
 | |
|    * - ``nsJSThingHashtable``
 | |
|      - ``nsJSThingHashtable.h``
 | |
|      -
 | |
|      - Adaptation of ``nsTHashtable``, see `XPCOM hashtable guide <https://developer.mozilla.org/docs/Mozilla/Tech/XPCOM/Guide/Hashtables>`__
 | |
|    * - ``mozilla::LinkedList``
 | |
|      - ``mozilla/LinkedList.h``
 | |
|      - ``std::list``
 | |
|      - Doubly-linked list
 | |
|    * - ``nsRef PtrHashtable``
 | |
|      - ``nsRefPtrHashtable.h``
 | |
|      - ``std::unordered_map``
 | |
|      - Adaptation of ``nsTHashtable``, see `XPCOM hashtable guide <https://developer.mozilla.org/docs/Mozilla/Tech/XPCOM/Guide/Hashtables>`__
 | |
|    * - ``mozilla::SegmentedVector``
 | |
|      - ``mozilla/SegmentedVector.h``
 | |
|      - ``std::deque`` w/o O(1) pop_front
 | |
|      - Doubly-linked list of vector elements
 | |
|    * - ``mozilla::SplayTree``
 | |
|      - ``mozilla/SplayTree.h``
 | |
|      -
 | |
|      - Quick access to recently-accessed elements (see `Wikipedia <https://en.wikipedia.org/wiki/Splay_tree>`__)
 | |
|    * - ``nsTArray``
 | |
|      - ``nsTArray.h``
 | |
|      - ``std::vector``
 | |
|      -
 | |
|    * - ``nsTHashtable``
 | |
|      - ``nsTHashtable.h``
 | |
|      - ``std::unordered_{map,set}``
 | |
|      - See `XPCOM hashtable guide <https://developer.mozilla.org/docs/Mozilla/Tech/XPCOM/Guide/Hashtables>`__,  you probably want a subclass
 | |
|    * - ``nsTObserverArray``
 | |
|      - ``nsTObserverArray.h``
 | |
|      -
 | |
|      - Like ``nsTArray``, but iteration is stable even through mutation
 | |
|    * - ``nsTPriorityQueue``
 | |
|      - ``nsTPriorityQueue.h``
 | |
|      - ``std::priority_queue``
 | |
|      - Unlike the STL class, not a container adapter
 | |
|    * - ``mozilla::Vector``
 | |
|      - ``mozilla/Vector.h``
 | |
|      - ``std::vector``
 | |
|      -
 | |
|    * - ``mozilla::Buffer``
 | |
|      - ``mozilla/Buffer.h``
 | |
|      -
 | |
|      - Unlike ``Array``, has a run-time variable length. Unlike ``Vector``, does not have capacity and growth mechanism. Unlike  ``Span``, owns  its buffer.
 | |
| 
 | |
| 
 | |
| Safety utilities
 | |
| ~~~~~~~~~~~~~~~~
 | |
| 
 | |
| .. list-table::
 | |
|    :widths: 25 25 25 25
 | |
|    :header-rows: 1
 | |
| 
 | |
|    * - Name
 | |
|      - Header
 | |
|      - STL equivalent
 | |
|      - Notes
 | |
|    * - ``mo- zilla::Array``
 | |
|      - ``mfbt/Array.h``
 | |
|      -
 | |
|      - safe array index
 | |
|    * - ``mozilla::AssertedCast``
 | |
|      - ``mfbt/Casting.h``
 | |
|      -
 | |
|      - casts
 | |
|    * - ``mozilla::CheckedInt``
 | |
|      - ``mfbt/CheckedInt.h``
 | |
|      -
 | |
|      - avoids overflow
 | |
|    * - ``nsCOMPtr``
 | |
|      - ``xpcom/base/nsCOMPtr.h``
 | |
|      - ``std::shared_ptr``
 | |
|      -
 | |
|    * - ``mozilla::EnumeratedArray``
 | |
|      - ``mfbt/EnumeratedArray.h``
 | |
|      - ``mozilla::Array``
 | |
|      -
 | |
|    * - ``mozilla::Maybe``
 | |
|      - ``mfbt/Maybe.h``
 | |
|      - ``std::optional``
 | |
|      -
 | |
|    * - ``mozilla::RangedPtr``
 | |
|      - ``mfbt/RangedPtr.h``
 | |
|      -
 | |
|      - like ``mozilla::Span`` but with two pointers instead of pointer and length
 | |
|    * - ``mozilla::RefPtr``
 | |
|      - ``mfbt/RefPtr.h``
 | |
|      - ``std::shared_ptr``
 | |
|      -
 | |
|    * - ``mozilla::Span``
 | |
|      - ``mozilla/Span.h``
 | |
|      - ``gsl::span``, ``absl::Span``, ``std::string_view``, ``std::u16string_view``
 | |
|      - Rust's slice concept for C++ (without borrow checking)
 | |
|    * - ``StaticRefPtr``
 | |
|      - ``xpcom/base/StaticPtr.h``
 | |
|      -
 | |
|      - ``nsRefPtr`` w/o static constructor
 | |
|    * - ``mozilla::UniquePtr``
 | |
|      - ``mfbt/UniquePtr.h``
 | |
|      - ``std::unique_ptr``
 | |
|      -
 | |
|    * - ``mozilla::WeakPtr``
 | |
|      - ``mfbt/WeakPtr.h``
 | |
|      - ``std::weak_ptr``
 | |
|      -
 | |
|    * - ``nsWeakPtr``
 | |
|      - ``xpcom/base/nsWeakPtr.h``
 | |
|      - ``std::weak_ptr``
 | |
|      -
 | |
| 
 | |
| 
 | |
| Strings
 | |
| ~~~~~~~
 | |
| 
 | |
| See the `Mozilla internal string
 | |
| guide <https://developer.mozilla.org/docs/Mozilla/Tech/XPCOM/Guide/Internal_strings>`__ for
 | |
| usage of ``nsAString`` (our copy-on-write replacement for
 | |
| ``std::u16string``) and ``nsACString`` (our copy-on-write replacement
 | |
| for ``std::string``).
 | |
| 
 | |
| Be sure not to introduce further uses of ``std::wstring``, which is not
 | |
| portable! (Some uses exist in the IPC code.)
 | |
| 
 | |
| 
 | |
| Algorithms
 | |
| ~~~~~~~~~~
 | |
| 
 | |
| .. list-table::
 | |
|    :widths: 25 25
 | |
| 
 | |
|    * - ``mozilla::BinarySearch``
 | |
|      - ``mfbt/BinarySearch.h``
 | |
|    * - ``mozilla::BitwiseCast``
 | |
|      - ``mfbt/Casting.h`` (strict aliasing-safe cast)
 | |
|    * - ``mozilla/MathAlgorithms.h``
 | |
|      - (rotate, ctlz, popcount, gcd, abs, lcm)
 | |
|    * - ``mozilla::RollingMean``
 | |
|      - ``mfbt/RollingMean.h`` ()
 | |
| 
 | |
| 
 | |
| Concurrency
 | |
| ~~~~~~~~~~~
 | |
| 
 | |
| .. list-table::
 | |
|    :widths: 25 25 25 25
 | |
|    :header-rows: 1
 | |
| 
 | |
|    * - Name
 | |
|      - Header
 | |
|      - STL/boost equivalent
 | |
|      - Notes
 | |
|    * - ``mozilla::Atomic``
 | |
|      - mfbt/Atomic.h
 | |
|      - ``std::atomic``
 | |
|      -
 | |
|    * - ``mozilla::CondVar``
 | |
|      - xpcom/threads/CondVar.h
 | |
|      - ``std::condition_variable``
 | |
|      -
 | |
|    * - ``mozilla::DataMutex``
 | |
|      - xpcom/threads/DataMutex.h
 | |
|      - ``boost::synchronized_value``
 | |
|      -
 | |
|    * - ``mozilla::Monitor``
 | |
|      - xpcom/threads/Monitor.h
 | |
|      -
 | |
|      -
 | |
|    * - ``mozilla::Mutex``
 | |
|      - xpcom/threads/Mutex.h
 | |
|      - ``std::mutex``
 | |
|      -
 | |
|    * - ``mozilla::ReentrantMonitor``
 | |
|      - xpcom/threads/ReentrantMonitor.h
 | |
|      -
 | |
|      -
 | |
|    * - ``mozilla::StaticMutex``
 | |
|      - xpcom/base/StaticMutex.h
 | |
|      - ``std::mutex``
 | |
|      - Mutex that can (and in fact, must) be used as a global/static variable.
 | |
| 
 | |
| 
 | |
| Miscellaneous
 | |
| ~~~~~~~~~~~~~
 | |
| 
 | |
| .. list-table::
 | |
|    :widths: 25 25 25 25
 | |
|    :header-rows: 1
 | |
| 
 | |
|    * - Name
 | |
|      - Header
 | |
|      - STL/boost equivalent
 | |
|      - Notes
 | |
|    * - ``mozilla::AlignedStorage``
 | |
|      - mfbt/Alignment.h
 | |
|      - ``std::aligned_storage``
 | |
|      -
 | |
|    * - ``mozilla::MaybeOneOf``
 | |
|      - mfbt/MaybeOneOf.h
 | |
|      - ``std::optional<std::variant<T1, T2>>``
 | |
|      - ~``mozilla::Maybe<union {T1, T2}>``   * -
 | |
|    * - ``mozilla::Pair``
 | |
|      - mfbt/Pair.h
 | |
|      - ``std::tuple<T1, T2>``
 | |
|      - minimal space!
 | |
|    * - ``mozilla::TimeStamp``
 | |
|      - xpcom/ds/TimeStamp.h
 | |
|      - ``std::chrono::time_point``
 | |
|      -
 | |
|    * - 
 | |
|      - mozilla/TypeTraits.h
 | |
|      - ``<type_traits>``
 | |
|      -
 | |
|    * - 
 | |
|      - mozilla/PodOperations.h
 | |
|      -
 | |
|      - C++ versions of ``memset``, ``memcpy``, etc.
 | |
|    * -
 | |
|      - mozilla/ArrayUtils.h
 | |
|      -
 | |
|      -
 | |
|    * -
 | |
|      - mozilla/Compression.h
 | |
|      -
 | |
|      -
 | |
|    * - 
 | |
|      - mozilla/Endian.h
 | |
|      -
 | |
|      -
 | |
|    * -
 | |
|      - mozilla/FloatingPoint.h
 | |
|      -
 | |
|      -
 | |
|    * - 
 | |
|      - mozilla/HashFunctions.h
 | |
|      - ``std::hash``
 | |
|      -
 | |
|    * - 
 | |
|      - mozilla/Move.h
 | |
|      - ``std::move``, ``std::swap``, ``std::forward``
 | |
|      -
 | |
| 
 | |
| 
 | |
| Mozilla data structures and standard C++ ranges and iterators
 | |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 | |
| 
 | |
| Some Mozilla-defined data structures provide STL-style
 | |
| `iterators <https://en.cppreference.com/w/cpp/named_req/Iterator>`__ and
 | |
| are usable in `range-based for
 | |
| loops <https://en.cppreference.com/w/cpp/language/range-for>`__ as well
 | |
| as STL `algorithms <https://en.cppreference.com/w/cpp/algorithm>`__.
 | |
| 
 | |
| Currently, these include:
 | |
| 
 | |
| .. list-table::
 | |
|    :widths: 16 16 16 16 16
 | |
|    :header-rows: 1
 | |
| 
 | |
|    * - Name
 | |
|      - Header
 | |
|      - Bug(s)
 | |
|      - Iterator category
 | |
|      - Notes
 | |
|    * - ``nsTArray``
 | |
|      - ``xpcom/ds/n sTArray.h``
 | |
|      - `1126552 <https://bugzilla.mozilla.org/show_bug.cgi?id=1126552>`__
 | |
|      - Random-access
 | |
|      - Also reverse-iterable. Also supports remove-erase pattern via RemoveElementsAt method. Also supports back-inserting output iterators via ``MakeBackInserter`` function.
 | |
|    * - ``nsBaseHashtable`` and subclasses: ``nsClassHashtable`` ``nsDataHashtable`` ``nsInterfaceHashtable`` ``nsJSThingHashtable`` ``nsRefPtrHashtable``
 | |
|      - ``xpcom/ds/nsBaseHashtable.h`` ``xpcom/ds/nsClassHashtable.h`` ``xpcom/ds/nsDataHashtable.h`` ``xpcom/ds/nsInterfaceHashtable.h`` ``xpcom/ds/nsJSThingHashtable.h`` ``xpcom/ds/nsRefPtrHashtable.h``
 | |
|      - `1575479 <https://bugzilla.mozilla.org/show_bug.cgi?id=1575479>`__
 | |
|      - Forward
 | |
|      -
 | |
|    * - ``nsCOMArray``
 | |
|      - ``xpcom/ds/nsCOMArray.h``
 | |
|      - `1342303 <https://bugzilla.mozilla.org/show_bug.cgi?id=1342303>`__
 | |
|      - Random-access
 | |
|      - Also reverse-iterable.
 | |
|    * - ``Array`` ``EnumerationArray`` ``RangedArray``
 | |
|      - ``mfbt/Array.h`` ``mfbt/EnumerationArray.h`` ``mfbt/RangedArray.h``
 | |
|      - `1216041 <https://bugzilla.mozilla.org/show_bug.cgi?id=1216041>`__
 | |
|      - Random-access
 | |
|      - Also reverse-iterable.
 | |
|    * - ``Buffer``
 | |
|      - ``mfbt/Buffer.h``
 | |
|      - `1512155 <https://bugzilla.mozilla.org/show_bug.cgi?id=1512155>`__
 | |
|      - Random-access
 | |
|      - Also reverse-iterable.
 | |
|    * - ``DoublyLinkedList``
 | |
|      - ``mfbt/DoublyLinkedList.h``
 | |
|      - `1277725 <https://bugzilla.mozilla.org/show_bug.cgi?id=1277725>`__
 | |
|      - Forward
 | |
|      -
 | |
|    * - ``EnumeratedRange``
 | |
|      - ``mfbt/EnumeratedRange.h``
 | |
|      - `1142999 <https://bugzilla.mozilla.org/show_bug.cgi?id=1142999>`__
 | |
|      - *Missing*
 | |
|      - Also reverse-iterable.
 | |
|    * - ``IntegerRange``
 | |
|      - ``mfbt/IntegerRange.h``
 | |
|      - `1126701 <https://bugzilla.mozilla.org/show_bug.cgi?id=1126701>`__
 | |
|      - *Missing*
 | |
|      - Also reverse-iterable.
 | |
|    * - ``SmallPointerArray``
 | |
|      - ``mfbt/SmallPointerArray.h``
 | |
|      - `1331718 <https://bugzilla.mozilla.org/show_bug.cgi?id=1331718>`__
 | |
|      - Random-access
 | |
|      -
 | |
|    * - ``Span``
 | |
|      - ``mfbt/Span.h``
 | |
|      - `1295611 <https://bugzilla.mozilla.org/show_bug.cgi?id=1295611>`__
 | |
|      - Random-access
 | |
|      - Also reverse-iterable.
 | |
| 
 | |
| Note that if the iterator category is stated as "missing", the type is
 | |
| probably only usable in range-based for. This is most likely just an
 | |
| omission, which could be easily fixed.
 | |
| 
 | |
| Useful in this context are also the class template ``IteratorRange``
 | |
| (which can be used to construct a range from any pair of iterators) and
 | |
| function template ``Reversed`` (which can be used to reverse any range),
 | |
| both defined in ``mfbt/ReverseIterator.h``
 | |
| 
 | |
| 
 | |
| Further C++ rules
 | |
| -----------------
 | |
| 
 | |
| 
 | |
| Don't use static constructors
 | |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 | |
| 
 | |
| (You probably shouldn't be using global variables to begin with. Quite
 | |
| apart from the weighty software-engineering arguments against them,
 | |
| globals affect startup time! But sometimes we have to do ugly things.)
 | |
| 
 | |
| Non-portable example:
 | |
| 
 | |
| .. code-block:: c++
 | |
| 
 | |
|    FooBarClass static_object(87, 92);
 | |
| 
 | |
|    void
 | |
|    bar()
 | |
|    {
 | |
|      if (static_object.count > 15) {
 | |
|         ...
 | |
|      }
 | |
|    }
 | |
| 
 | |
| Once upon a time, there were compiler bugs that could result in
 | |
| constructors not being called for global objects. Those bugs are
 | |
| probably long gone by now, but even with the feature working correctly,
 | |
| there are so many problems with correctly ordering C++ constructors that
 | |
| it's easier to just have an init function:
 | |
| 
 | |
| .. code-block:: c++
 | |
| 
 | |
|    static FooBarClass* static_object;
 | |
| 
 | |
|    FooBarClass*
 | |
|    getStaticObject()
 | |
|    {
 | |
|      if (!static_object)
 | |
|        static_object =
 | |
|          new FooBarClass(87, 92);
 | |
|      return static_object;
 | |
|    }
 | |
| 
 | |
|    void
 | |
|    bar()
 | |
|    {
 | |
|      if (getStaticObject()->count > 15) {
 | |
|        ...
 | |
|      }
 | |
|    }
 | |
| 
 | |
| 
 | |
| Don't use exceptions
 | |
| ~~~~~~~~~~~~~~~~~~~~
 | |
| 
 | |
| See the introduction to the "C++ language features" section at the start
 | |
| of this document.
 | |
| 
 | |
| 
 | |
| Don't use Run-time Type Information
 | |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 | |
| 
 | |
| See the introduction to the "C++ language features" section at the start
 | |
| of this document.
 | |
| 
 | |
| If you need runtime typing, you can achieve a similar result by adding a
 | |
| ``classOf()`` virtual member function to the base class of your
 | |
| hierarchy and overriding that member function in each subclass. If
 | |
| ``classOf()`` returns a unique value for each class in the hierarchy,
 | |
| you'll be able to do type comparisons at runtime.
 | |
| 
 | |
| 
 | |
| Don't use the C++ standard library (including iostream and locale)
 | |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 | |
| 
 | |
| See the section "C++ and Mozilla standard libraries".
 | |
| 
 | |
| 
 | |
| Use C++ lambdas, but with care
 | |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 | |
| 
 | |
| C++ lambdas are supported across all our compilers now. Rejoice! We
 | |
| recommend explicitly listing out the variables that you capture in the
 | |
| lambda, both for documentation purposes, and to double-check that you're
 | |
| only capturing what you expect to capture.
 | |
| 
 | |
| 
 | |
| Use namespaces
 | |
| ~~~~~~~~~~~~~~
 | |
| 
 | |
| Namespaces may be used according to the style guidelines in :ref:`C++ Coding style`.
 | |
| 
 | |
| 
 | |
| Don't mix varargs and inlines
 | |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 | |
| 
 | |
| What? Why are you using varargs to begin with?! Stop that at once!
 | |
| 
 | |
| 
 | |
| Make header files compatible with C and C++
 | |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 | |
| 
 | |
| Non-portable example:
 | |
| 
 | |
| .. code-block:: c++
 | |
| 
 | |
|    /*oldCheader.h*/
 | |
|    int existingCfunction(char*);
 | |
|    int anotherExistingCfunction(char*);
 | |
| 
 | |
|    /* oldCfile.c */
 | |
|    #include "oldCheader.h"
 | |
|    ...
 | |
| 
 | |
|    // new file.cpp
 | |
|    extern "C" {
 | |
|    #include "oldCheader.h"
 | |
|    };
 | |
|    ...
 | |
| 
 | |
| If you make new header files with exposed C interfaces, make the header
 | |
| files work correctly when they are included by both C and C++ files.
 | |
| 
 | |
| (If you need to include a C header in new C++ files, that should just
 | |
| work. If not, it's the C header maintainer's fault, so fix the header if
 | |
| you can, and if not, whatever hack you come up with will probably be
 | |
| fine.)
 | |
| 
 | |
| Portable example:
 | |
| 
 | |
| .. code-block:: c++
 | |
| 
 | |
|    /* oldCheader.h*/
 | |
|    PR_BEGIN_EXTERN_C
 | |
|    int existingCfunction(char*);
 | |
|    int anotherExistingCfunction(char*);
 | |
|    PR_END_EXTERN_C
 | |
| 
 | |
|    /* oldCfile.c */
 | |
|    #include "oldCheader.h"
 | |
|    ...
 | |
| 
 | |
|    // new file.cpp
 | |
|    #include "oldCheader.h"
 | |
|    ...
 | |
| 
 | |
| There are number of reasons for doing this, other than just good style.
 | |
| For one thing, you are making life easier for everyone else, doing the
 | |
| work in one common place (the header file) instead of all the C++ files
 | |
| that include it. Also, by making the C header safe for C++, you document
 | |
| that "hey, this file is now being included in C++". That's a good thing.
 | |
| You also avoid a big portability nightmare that is nasty to fix...
 | |
| 
 | |
| 
 | |
| Use override on subclass virtual member functions
 | |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 | |
| 
 | |
| The ``override`` keyword is supported in C++11 and in all our supported
 | |
| compilers, and it catches bugs.
 | |
| 
 | |
| 
 | |
| Always declare a copy constructor and assignment operator
 | |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 | |
| 
 | |
| Many classes shouldn't be copied or assigned. If you're writing one of
 | |
| these, the way to enforce your policy is to declare a deleted copy
 | |
| constructor as private and not supply a definition. While you're at it,
 | |
| do the same for the assignment operator used for assignment of objects
 | |
| of the same class. Example:
 | |
| 
 | |
| .. code-block:: c++
 | |
| 
 | |
|    class Foo {
 | |
|      ...
 | |
|      private:
 | |
|        Foo(const Foo& x) = delete;
 | |
|        Foo& operator=(const Foo& x) = delete;
 | |
|    };
 | |
| 
 | |
| Any code that implicitly calls the copy constructor will hit a
 | |
| compile-time error. That way nothing happens in the dark. When a user's
 | |
| code won't compile, they'll see that they were passing by value, when
 | |
| they meant to pass by reference (oops).
 | |
| 
 | |
| 
 | |
| Be careful of overloaded methods with like signatures
 | |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 | |
| 
 | |
| It's best to avoid overloading methods when the type signature of the
 | |
| methods differs only by one "abstract" type (e.g. ``PR_Int32`` or
 | |
| ``int32``). What you will find as you move that code to different
 | |
| platforms, is suddenly on the Foo2000 compiler your overloaded methods
 | |
| will have the same type-signature.
 | |
| 
 | |
| 
 | |
| Type scalar constants to avoid unexpected ambiguities
 | |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 | |
| 
 | |
| Non-portable code:
 | |
| 
 | |
| .. code-block:: c++
 | |
| 
 | |
|    class FooClass {
 | |
|      // having such similar signatures
 | |
|      // is a bad idea in the first place.
 | |
|      void doit(long);
 | |
|      void doit(short);
 | |
|    };
 | |
| 
 | |
|    void
 | |
|    B::foo(FooClass* xyz)
 | |
|    {
 | |
|      xyz->doit(45);
 | |
|    }
 | |
| 
 | |
| Be sure to type your scalar constants, e.g., ``uint32_t(10)`` or
 | |
| ``10L``. Otherwise, you can produce ambiguous function calls which
 | |
| potentially could resolve to multiple methods, particularly if you
 | |
| haven't followed (2) above. Not all of the compilers will flag ambiguous
 | |
| method calls.
 | |
| 
 | |
| Portable code:
 | |
| 
 | |
| .. code-block:: c++
 | |
| 
 | |
|    class FooClass {
 | |
|      // having such similar signatures
 | |
|      // is a bad idea in the first place.
 | |
|      void doit(long);
 | |
|      void doit(short);
 | |
|    };
 | |
| 
 | |
|    void
 | |
|    B::foo(FooClass* xyz)
 | |
|    {
 | |
|      xyz->doit(45L);
 | |
|    }
 | |
| 
 | |
| 
 | |
| Use nsCOMPtr in XPCOM code
 | |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~
 | |
| 
 | |
| See the ``nsCOMPtr`` `User
 | |
| Manual <https://developer.mozilla.org/en-US/docs/Using_nsCOMPtr>`__ for
 | |
| usage details.
 | |
| 
 | |
| 
 | |
| Don't use identifiers that start with an underscore
 | |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 | |
| 
 | |
| This rule occasionally surprises people who've been hacking C++ for
 | |
| decades. But it comes directly from the C++ standard!
 | |
| 
 | |
| According to the C++ Standard, 17.4.3.1.2 Global Names
 | |
| [lib.global.names], paragraph 1:
 | |
| 
 | |
| Certain sets of names and function signatures are always reserved to the
 | |
| implementation:
 | |
| 
 | |
| -  Each name that contains a double underscore (__) or begins with an
 | |
|    underscore followed by an uppercase letter (2.11) is reserved to the
 | |
|    implementation for any use.
 | |
| -  **Each name that begins with an underscore is reserved to the
 | |
|    implementation** for use as a name in the global namespace.
 | |
| 
 | |
| 
 | |
| Stuff that is good to do for C or C++
 | |
| -------------------------------------
 | |
| 
 | |
| 
 | |
| Avoid conditional #includes when possible
 | |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 | |
| 
 | |
| Don't write an ``#include`` inside an ``#ifdef`` if you could instead
 | |
| put it outside. Unconditional includes are better because they make the
 | |
| compilation more similar across all platforms and configurations, so
 | |
| you're less likely to cause stupid compiler errors on someone else's
 | |
| favorite platform that you never use.
 | |
| 
 | |
| Bad code example:
 | |
| 
 | |
| .. code-block:: c++
 | |
| 
 | |
|    #ifdef MOZ_ENABLE_JPEG_FOUR_BILLION
 | |
|    #include <stdlib.h>   // <--- don't do this
 | |
|    #include "jpeg4e9.h"  // <--- only do this if the header really might not be there
 | |
|    #endif
 | |
| 
 | |
| Of course when you're including different system files for different
 | |
| machines, you don't have much choice. That's different.
 | |
| 
 | |
| 
 | |
| Every .cpp source file should have a unique name
 | |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 | |
| 
 | |
| Every object file linked into libxul needs to have a unique name. Avoid
 | |
| generic names like nsModule.cpp and instead use nsPlacesModule.cpp.
 | |
| 
 | |
| 
 | |
| Turn on warnings for your compiler, and then write warning free code
 | |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 | |
| 
 | |
| What generates a warning on one platform will generate errors on
 | |
| another. Turn warnings on. Write warning-free code. It's good for you.
 | |
| Treat warnings as errors by adding
 | |
| ``ac_add_options --enable-warnings-as-errors`` to your mozconfig file.
 | |
| 
 | |
| 
 | |
| Use the same type for all bitfields in a ``struct`` or ``class``
 | |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 | |
| 
 | |
| Some compilers do not pack the bits when different bitfields are given
 | |
| different types. For example, the following struct might have a size of
 | |
| 8 bytes, even though it would fit in 1:
 | |
| 
 | |
| .. code-block:: c++
 | |
| 
 | |
|    struct {
 | |
|      char ch: 1;
 | |
|      int i: 1;
 | |
|    };
 | |
| 
 | |
| 
 | |
| Don't use an enum type for a bitfield
 | |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 | |
| 
 | |
| The classic example of this is using ``PRBool`` for a boolean bitfield.
 | |
| Don't do that. ``PRBool`` is a signed integer type, so the bitfield's
 | |
| value when set will be ``-1`` instead of ``+1``, which---I know,
 | |
| *crazy*, right? The things C++ hackers used to have to put up with...
 | |
| 
 | |
| You shouldn't be using ``PRBool`` anyway. Use ``bool``. Bitfields of
 | |
| type ``bool`` are fine.
 | |
| 
 | |
| Enums are signed on some platforms (in some configurations) and unsigned
 | |
| on others and therefore unsuitable for writing portable code when every
 | |
| bit counts, even if they happen to work on your system.
 |