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 * - ``nsJSThingHashtable`` 406 - ``nsJSThingHashtable.h`` 407 - 408 - Adaptation of ``nsTHashtable``, see `XPCOM hashtable guide <https://developer.mozilla.org/docs/Mozilla/Tech/XPCOM/Guide/Hashtables>`__ 409 * - ``mozilla::LinkedList`` 410 - ``mozilla/LinkedList.h`` 411 - ``std::list`` 412 - Doubly-linked list 413 * - ``nsRef PtrHashtable`` 414 - ``nsRefPtrHashtable.h`` 415 - ``std::unordered_map`` 416 - Adaptation of ``nsTHashtable``, see `XPCOM hashtable guide <https://developer.mozilla.org/docs/Mozilla/Tech/XPCOM/Guide/Hashtables>`__ 417 * - ``mozilla::SegmentedVector`` 418 - ``mozilla/SegmentedVector.h`` 419 - ``std::deque`` w/o O(1) pop_front 420 - Doubly-linked list of vector elements 421 * - ``mozilla::SplayTree`` 422 - ``mozilla/SplayTree.h`` 423 - 424 - Quick access to recently-accessed elements (see `Wikipedia <https://en.wikipedia.org/wiki/Splay_tree>`__) 425 * - ``nsTArray`` 426 - ``nsTArray.h`` 427 - ``std::vector`` 428 - 429 * - ``nsTHashtable`` 430 - ``nsTHashtable.h`` 431 - ``std::unordered_{map,set}`` 432 - See `XPCOM hashtable guide <https://developer.mozilla.org/docs/Mozilla/Tech/XPCOM/Guide/Hashtables>`__, you probably want a subclass 433 * - ``nsTObserverArray`` 434 - ``nsTObserverArray.h`` 435 - 436 - Like ``nsTArray``, but iteration is stable even through mutation 437 * - ``nsTPriorityQueue`` 438 - ``nsTPriorityQueue.h`` 439 - ``std::priority_queue`` 440 - Unlike the STL class, not a container adapter 441 * - ``mozilla::Vector`` 442 - ``mozilla/Vector.h`` 443 - ``std::vector`` 444 - 445 * - ``mozilla::Buffer`` 446 - ``mozilla/Buffer.h`` 447 - 448 - Unlike ``Array``, has a run-time variable length. Unlike ``Vector``, does not have capacity and growth mechanism. Unlike ``Span``, owns its buffer. 449 450 451Safety utilities 452~~~~~~~~~~~~~~~~ 453 454.. list-table:: 455 :widths: 25 25 25 25 456 :header-rows: 1 457 458 * - Name 459 - Header 460 - STL equivalent 461 - Notes 462 * - ``mo- zilla::Array`` 463 - ``mfbt/Array.h`` 464 - 465 - safe array index 466 * - ``mozilla::AssertedCast`` 467 - ``mfbt/Casting.h`` 468 - 469 - casts 470 * - ``mozilla::CheckedInt`` 471 - ``mfbt/CheckedInt.h`` 472 - 473 - avoids overflow 474 * - ``nsCOMPtr`` 475 - ``xpcom/base/nsCOMPtr.h`` 476 - ``std::shared_ptr`` 477 - 478 * - ``mozilla::EnumeratedArray`` 479 - ``mfbt/EnumeratedArray.h`` 480 - ``mozilla::Array`` 481 - 482 * - ``mozilla::Maybe`` 483 - ``mfbt/Maybe.h`` 484 - ``std::optional`` 485 - 486 * - ``mozilla::RangedPtr`` 487 - ``mfbt/RangedPtr.h`` 488 - 489 - like ``mozilla::Span`` but with two pointers instead of pointer and length 490 * - ``mozilla::RefPtr`` 491 - ``mfbt/RefPtr.h`` 492 - ``std::shared_ptr`` 493 - 494 * - ``mozilla::Span`` 495 - ``mozilla/Span.h`` 496 - ``gsl::span``, ``absl::Span``, ``std::string_view``, ``std::u16string_view`` 497 - Rust's slice concept for C++ (without borrow checking) 498 * - ``StaticRefPtr`` 499 - ``xpcom/base/StaticPtr.h`` 500 - 501 - ``nsRefPtr`` w/o static constructor 502 * - ``mozilla::UniquePtr`` 503 - ``mfbt/UniquePtr.h`` 504 - ``std::unique_ptr`` 505 - 506 * - ``mozilla::WeakPtr`` 507 - ``mfbt/WeakPtr.h`` 508 - ``std::weak_ptr`` 509 - 510 * - ``nsWeakPtr`` 511 - ``xpcom/base/nsWeakPtr.h`` 512 - ``std::weak_ptr`` 513 - 514 515 516Strings 517~~~~~~~ 518 519See the `Mozilla internal string 520guide <https://developer.mozilla.org/docs/Mozilla/Tech/XPCOM/Guide/Internal_strings>`__ for 521usage of ``nsAString`` (our copy-on-write replacement for 522``std::u16string``) and ``nsACString`` (our copy-on-write replacement 523for ``std::string``). 524 525Be sure not to introduce further uses of ``std::wstring``, which is not 526portable! (Some uses exist in the IPC code.) 527 528 529Algorithms 530~~~~~~~~~~ 531 532.. list-table:: 533 :widths: 25 25 534 535 * - ``mozilla::BinarySearch`` 536 - ``mfbt/BinarySearch.h`` 537 * - ``mozilla::BitwiseCast`` 538 - ``mfbt/Casting.h`` (strict aliasing-safe cast) 539 * - ``mozilla/MathAlgorithms.h`` 540 - (rotate, ctlz, popcount, gcd, abs, lcm) 541 * - ``mozilla::RollingMean`` 542 - ``mfbt/RollingMean.h`` () 543 544 545Concurrency 546~~~~~~~~~~~ 547 548.. list-table:: 549 :widths: 25 25 25 25 550 :header-rows: 1 551 552 * - Name 553 - Header 554 - STL/boost equivalent 555 - Notes 556 * - ``mozilla::Atomic`` 557 - mfbt/Atomic.h 558 - ``std::atomic`` 559 - 560 * - ``mozilla::CondVar`` 561 - xpcom/threads/CondVar.h 562 - ``std::condition_variable`` 563 - 564 * - ``mozilla::DataMutex`` 565 - xpcom/threads/DataMutex.h 566 - ``boost::synchronized_value`` 567 - 568 * - ``mozilla::Monitor`` 569 - xpcom/threads/Monitor.h 570 - 571 - 572 * - ``mozilla::Mutex`` 573 - xpcom/threads/Mutex.h 574 - ``std::mutex`` 575 - 576 * - ``mozilla::ReentrantMonitor`` 577 - xpcom/threads/ReentrantMonitor.h 578 - 579 - 580 * - ``mozilla::StaticMutex`` 581 - xpcom/base/StaticMutex.h 582 - ``std::mutex`` 583 - Mutex that can (and in fact, must) be used as a global/static variable. 584 585 586Miscellaneous 587~~~~~~~~~~~~~ 588 589.. list-table:: 590 :widths: 25 25 25 25 591 :header-rows: 1 592 593 * - Name 594 - Header 595 - STL/boost equivalent 596 - Notes 597 * - ``mozilla::AlignedStorage`` 598 - mfbt/Alignment.h 599 - ``std::aligned_storage`` 600 - 601 * - ``mozilla::MaybeOneOf`` 602 - mfbt/MaybeOneOf.h 603 - ``std::optional<std::variant<T1, T2>>`` 604 - ~``mozilla::Maybe<union {T1, T2}>`` * - 605 * - ``mozilla::Pair`` 606 - mfbt/Pair.h 607 - ``std::tuple<T1, T2>`` 608 - minimal space! 609 * - ``mozilla::TimeStamp`` 610 - xpcom/ds/TimeStamp.h 611 - ``std::chrono::time_point`` 612 - 613 * - 614 - mozilla/TypeTraits.h 615 - ``<type_traits>`` 616 - 617 * - 618 - mozilla/PodOperations.h 619 - 620 - C++ versions of ``memset``, ``memcpy``, etc. 621 * - 622 - mozilla/ArrayUtils.h 623 - 624 - 625 * - 626 - mozilla/Compression.h 627 - 628 - 629 * - 630 - mozilla/Endian.h 631 - 632 - 633 * - 634 - mozilla/FloatingPoint.h 635 - 636 - 637 * - 638 - mozilla/HashFunctions.h 639 - ``std::hash`` 640 - 641 * - 642 - mozilla/Move.h 643 - ``std::move``, ``std::swap``, ``std::forward`` 644 - 645 646 647Mozilla data structures and standard C++ ranges and iterators 648~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 649 650Some Mozilla-defined data structures provide STL-style 651`iterators <https://en.cppreference.com/w/cpp/named_req/Iterator>`__ and 652are usable in `range-based for 653loops <https://en.cppreference.com/w/cpp/language/range-for>`__ as well 654as STL `algorithms <https://en.cppreference.com/w/cpp/algorithm>`__. 655 656Currently, these include: 657 658.. list-table:: 659 :widths: 16 16 16 16 16 660 :header-rows: 1 661 662 * - Name 663 - Header 664 - Bug(s) 665 - Iterator category 666 - Notes 667 * - ``nsTArray`` 668 - ``xpcom/ds/n sTArray.h`` 669 - `1126552 <https://bugzilla.mozilla.org/show_bug.cgi?id=1126552>`__ 670 - Random-access 671 - Also reverse-iterable. Also supports remove-erase pattern via RemoveElementsAt method. Also supports back-inserting output iterators via ``MakeBackInserter`` function. 672 * - ``nsBaseHashtable`` and subclasses: ``nsClassHashtable`` ``nsDataHashtable`` ``nsInterfaceHashtable`` ``nsJSThingHashtable`` ``nsRefPtrHashtable`` 673 - ``xpcom/ds/nsBaseHashtable.h`` ``xpcom/ds/nsClassHashtable.h`` ``xpcom/ds/nsDataHashtable.h`` ``xpcom/ds/nsInterfaceHashtable.h`` ``xpcom/ds/nsJSThingHashtable.h`` ``xpcom/ds/nsRefPtrHashtable.h`` 674 - `1575479 <https://bugzilla.mozilla.org/show_bug.cgi?id=1575479>`__ 675 - Forward 676 - 677 * - ``nsCOMArray`` 678 - ``xpcom/ds/nsCOMArray.h`` 679 - `1342303 <https://bugzilla.mozilla.org/show_bug.cgi?id=1342303>`__ 680 - Random-access 681 - Also reverse-iterable. 682 * - ``Array`` ``EnumerationArray`` ``RangedArray`` 683 - ``mfbt/Array.h`` ``mfbt/EnumerationArray.h`` ``mfbt/RangedArray.h`` 684 - `1216041 <https://bugzilla.mozilla.org/show_bug.cgi?id=1216041>`__ 685 - Random-access 686 - Also reverse-iterable. 687 * - ``Buffer`` 688 - ``mfbt/Buffer.h`` 689 - `1512155 <https://bugzilla.mozilla.org/show_bug.cgi?id=1512155>`__ 690 - Random-access 691 - Also reverse-iterable. 692 * - ``DoublyLinkedList`` 693 - ``mfbt/DoublyLinkedList.h`` 694 - `1277725 <https://bugzilla.mozilla.org/show_bug.cgi?id=1277725>`__ 695 - Forward 696 - 697 * - ``EnumeratedRange`` 698 - ``mfbt/EnumeratedRange.h`` 699 - `1142999 <https://bugzilla.mozilla.org/show_bug.cgi?id=1142999>`__ 700 - *Missing* 701 - Also reverse-iterable. 702 * - ``IntegerRange`` 703 - ``mfbt/IntegerRange.h`` 704 - `1126701 <https://bugzilla.mozilla.org/show_bug.cgi?id=1126701>`__ 705 - *Missing* 706 - Also reverse-iterable. 707 * - ``SmallPointerArray`` 708 - ``mfbt/SmallPointerArray.h`` 709 - `1331718 <https://bugzilla.mozilla.org/show_bug.cgi?id=1331718>`__ 710 - Random-access 711 - 712 * - ``Span`` 713 - ``mfbt/Span.h`` 714 - `1295611 <https://bugzilla.mozilla.org/show_bug.cgi?id=1295611>`__ 715 - Random-access 716 - Also reverse-iterable. 717 718Note that if the iterator category is stated as "missing", the type is 719probably only usable in range-based for. This is most likely just an 720omission, which could be easily fixed. 721 722Useful in this context are also the class template ``IteratorRange`` 723(which can be used to construct a range from any pair of iterators) and 724function template ``Reversed`` (which can be used to reverse any range), 725both defined in ``mfbt/ReverseIterator.h`` 726 727 728Further C++ rules 729----------------- 730 731 732Don't use static constructors 733~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 734 735(You probably shouldn't be using global variables to begin with. Quite 736apart from the weighty software-engineering arguments against them, 737globals affect startup time! But sometimes we have to do ugly things.) 738 739Non-portable example: 740 741.. code-block:: c++ 742 743 FooBarClass static_object(87, 92); 744 745 void 746 bar() 747 { 748 if (static_object.count > 15) { 749 ... 750 } 751 } 752 753Once upon a time, there were compiler bugs that could result in 754constructors not being called for global objects. Those bugs are 755probably long gone by now, but even with the feature working correctly, 756there are so many problems with correctly ordering C++ constructors that 757it's easier to just have an init function: 758 759.. code-block:: c++ 760 761 static FooBarClass* static_object; 762 763 FooBarClass* 764 getStaticObject() 765 { 766 if (!static_object) 767 static_object = 768 new FooBarClass(87, 92); 769 return static_object; 770 } 771 772 void 773 bar() 774 { 775 if (getStaticObject()->count > 15) { 776 ... 777 } 778 } 779 780 781Don't use exceptions 782~~~~~~~~~~~~~~~~~~~~ 783 784See the introduction to the "C++ language features" section at the start 785of this document. 786 787 788Don't use Run-time Type Information 789~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 790 791See the introduction to the "C++ language features" section at the start 792of this document. 793 794If you need runtime typing, you can achieve a similar result by adding a 795``classOf()`` virtual member function to the base class of your 796hierarchy and overriding that member function in each subclass. If 797``classOf()`` returns a unique value for each class in the hierarchy, 798you'll be able to do type comparisons at runtime. 799 800 801Don't use the C++ standard library (including iostream and locale) 802~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 803 804See the section "C++ and Mozilla standard libraries". 805 806 807Use C++ lambdas, but with care 808~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 809 810C++ lambdas are supported across all our compilers now. Rejoice! We 811recommend explicitly listing out the variables that you capture in the 812lambda, both for documentation purposes, and to double-check that you're 813only capturing what you expect to capture. 814 815 816Use namespaces 817~~~~~~~~~~~~~~ 818 819Namespaces may be used according to the style guidelines in :ref:`C++ Coding style`. 820 821 822Don't mix varargs and inlines 823~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 824 825What? Why are you using varargs to begin with?! Stop that at once! 826 827 828Make header files compatible with C and C++ 829~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 830 831Non-portable example: 832 833.. code-block:: c++ 834 835 /*oldCheader.h*/ 836 int existingCfunction(char*); 837 int anotherExistingCfunction(char*); 838 839 /* oldCfile.c */ 840 #include "oldCheader.h" 841 ... 842 843 // new file.cpp 844 extern "C" { 845 #include "oldCheader.h" 846 }; 847 ... 848 849If you make new header files with exposed C interfaces, make the header 850files work correctly when they are included by both C and C++ files. 851 852(If you need to include a C header in new C++ files, that should just 853work. If not, it's the C header maintainer's fault, so fix the header if 854you can, and if not, whatever hack you come up with will probably be 855fine.) 856 857Portable example: 858 859.. code-block:: c++ 860 861 /* oldCheader.h*/ 862 PR_BEGIN_EXTERN_C 863 int existingCfunction(char*); 864 int anotherExistingCfunction(char*); 865 PR_END_EXTERN_C 866 867 /* oldCfile.c */ 868 #include "oldCheader.h" 869 ... 870 871 // new file.cpp 872 #include "oldCheader.h" 873 ... 874 875There are number of reasons for doing this, other than just good style. 876For one thing, you are making life easier for everyone else, doing the 877work in one common place (the header file) instead of all the C++ files 878that include it. Also, by making the C header safe for C++, you document 879that "hey, this file is now being included in C++". That's a good thing. 880You also avoid a big portability nightmare that is nasty to fix... 881 882 883Use override on subclass virtual member functions 884~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 885 886The ``override`` keyword is supported in C++11 and in all our supported 887compilers, and it catches bugs. 888 889 890Always declare a copy constructor and assignment operator 891~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 892 893Many classes shouldn't be copied or assigned. If you're writing one of 894these, the way to enforce your policy is to declare a deleted copy 895constructor as private and not supply a definition. While you're at it, 896do the same for the assignment operator used for assignment of objects 897of the same class. Example: 898 899.. code-block:: c++ 900 901 class Foo { 902 ... 903 private: 904 Foo(const Foo& x) = delete; 905 Foo& operator=(const Foo& x) = delete; 906 }; 907 908Any code that implicitly calls the copy constructor will hit a 909compile-time error. That way nothing happens in the dark. When a user's 910code won't compile, they'll see that they were passing by value, when 911they meant to pass by reference (oops). 912 913 914Be careful of overloaded methods with like signatures 915~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 916 917It's best to avoid overloading methods when the type signature of the 918methods differs only by one "abstract" type (e.g. ``PR_Int32`` or 919``int32``). What you will find as you move that code to different 920platforms, is suddenly on the Foo2000 compiler your overloaded methods 921will have the same type-signature. 922 923 924Type scalar constants to avoid unexpected ambiguities 925~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 926 927Non-portable code: 928 929.. code-block:: c++ 930 931 class FooClass { 932 // having such similar signatures 933 // is a bad idea in the first place. 934 void doit(long); 935 void doit(short); 936 }; 937 938 void 939 B::foo(FooClass* xyz) 940 { 941 xyz->doit(45); 942 } 943 944Be sure to type your scalar constants, e.g., ``uint32_t(10)`` or 945``10L``. Otherwise, you can produce ambiguous function calls which 946potentially could resolve to multiple methods, particularly if you 947haven't followed (2) above. Not all of the compilers will flag ambiguous 948method calls. 949 950Portable code: 951 952.. code-block:: c++ 953 954 class FooClass { 955 // having such similar signatures 956 // is a bad idea in the first place. 957 void doit(long); 958 void doit(short); 959 }; 960 961 void 962 B::foo(FooClass* xyz) 963 { 964 xyz->doit(45L); 965 } 966 967 968Use nsCOMPtr in XPCOM code 969~~~~~~~~~~~~~~~~~~~~~~~~~~ 970 971See the ``nsCOMPtr`` `User 972Manual <https://developer.mozilla.org/en-US/docs/Using_nsCOMPtr>`__ for 973usage details. 974 975 976Don't use identifiers that start with an underscore 977~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 978 979This rule occasionally surprises people who've been hacking C++ for 980decades. But it comes directly from the C++ standard! 981 982According to the C++ Standard, 17.4.3.1.2 Global Names 983[lib.global.names], paragraph 1: 984 985Certain sets of names and function signatures are always reserved to the 986implementation: 987 988- Each name that contains a double underscore (__) or begins with an 989 underscore followed by an uppercase letter (2.11) is reserved to the 990 implementation for any use. 991- **Each name that begins with an underscore is reserved to the 992 implementation** for use as a name in the global namespace. 993 994 995Stuff that is good to do for C or C++ 996------------------------------------- 997 998 999Avoid conditional #includes when possible 1000~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1001 1002Don't write an ``#include`` inside an ``#ifdef`` if you could instead 1003put it outside. Unconditional includes are better because they make the 1004compilation more similar across all platforms and configurations, so 1005you're less likely to cause stupid compiler errors on someone else's 1006favorite platform that you never use. 1007 1008Bad code example: 1009 1010.. code-block:: c++ 1011 1012 #ifdef MOZ_ENABLE_JPEG_FOUR_BILLION 1013 #include <stdlib.h> // <--- don't do this 1014 #include "jpeg4e9.h" // <--- only do this if the header really might not be there 1015 #endif 1016 1017Of course when you're including different system files for different 1018machines, you don't have much choice. That's different. 1019 1020 1021Every .cpp source file should have a unique name 1022~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1023 1024Every object file linked into libxul needs to have a unique name. Avoid 1025generic names like nsModule.cpp and instead use nsPlacesModule.cpp. 1026 1027 1028Turn on warnings for your compiler, and then write warning free code 1029~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1030 1031What generates a warning on one platform will generate errors on 1032another. Turn warnings on. Write warning-free code. It's good for you. 1033Treat warnings as errors by adding 1034``ac_add_options --enable-warnings-as-errors`` to your mozconfig file. 1035 1036 1037Use the same type for all bitfields in a ``struct`` or ``class`` 1038~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1039 1040Some compilers do not pack the bits when different bitfields are given 1041different types. For example, the following struct might have a size of 10428 bytes, even though it would fit in 1: 1043 1044.. code-block:: c++ 1045 1046 struct { 1047 char ch: 1; 1048 int i: 1; 1049 }; 1050 1051 1052Don't use an enum type for a bitfield 1053~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1054 1055The classic example of this is using ``PRBool`` for a boolean bitfield. 1056Don't do that. ``PRBool`` is a signed integer type, so the bitfield's 1057value when set will be ``-1`` instead of ``+1``, which---I know, 1058*crazy*, right? The things C++ hackers used to have to put up with... 1059 1060You shouldn't be using ``PRBool`` anyway. Use ``bool``. Bitfields of 1061type ``bool`` are fine. 1062 1063Enums are signed on some platforms (in some configurations) and unsigned 1064on others and therefore unsuitable for writing portable code when every 1065bit counts, even if they happen to work on your system. 1066