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