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