Documentation

The main docs for libstdc++ hacking are in Appendix A and Appendix B of the manual:

The Libstdcxx/WritingTests wiki page is useful too.

Header naming

stl_xxx.h is for headers that originated with the SGI STL. We do not use "STL" to refer to "the standard library", only to the subset that comes from the STL (as Wikipedia says, "The STL and the C++ Standard Library are two distinct entities.")

Name qualification

Except for the handful of functions that are explicitly intended as ADL customization points (e.g. swap, make_error_code, etc.) all calls to non-member functions should be qualified with a namespace, to prevent ADL.

It is necessary to disable ADL even for reserved names such as __rotate because otherwise ADL can cause compilation to fail when an associated class is incomplete (e.g., see Bug 60497, P2538R1, and P2600R0). Even without unwanted template instantiations, name lookup is typically faster to compile without ADL, because the compiler does not have to determine the associated namespaces and search in them.

C++20 Customization Point Objects

C++20 introduces a number of CPOs (std::ranges::swap, std::ranges::begin, std::strong_order etc.). These must be declared with care. Each CPO has an associated class type, and a "poison pill" overload that causes name lookup for the customization point to only consider names found by ADL. The poison pill works by ensuring that ordinary unqualified lookup for the name (e.g. begin) finds the poison pill, which is deleted and/or has the wrong number of arguments. Consequently, when the poison pill is visible, the only viable candidates for an unqualified call to that name will be overloads that are found via ADL. The CPO class type and the poison pill must be in a non-inline namespace nested below std, so that the poison pill is not visible for any name lookup except that done by the CPO type. The CPO object itself must be in a different namespace (so that it doesn't clash with the poison pill declaration). To avoid clashing with hidden friend functions with the same name, the CPO object must be in an inline namespace of its own.

So the definition of a CPO std::foo should look like:

   1 namespace std {
   2   namespace __foo {
   3     void foo() = delete; // poison pill
   4 
   5     // Test whether foo(t) can be found via ADL.
   6     template<class T> concept __adl_foo = requires(T t) { foo(t); };
   7 
   8     struct _Foo {
   9        decltype(auto) operator()(auto&& t) {
  10          if constexpr (__adl_foo<decltype(t)>)
  11            foo(t); // use ADL to find foo
  12          else
  13            // ...
  14     };
  15   } // namespace __foo
  16   inline namespace _Cpo {
  17     inline constexpr __foo::_Foo foo{};
  18   }
  19 }

We currently use the following namespaces for the CPO types and poison pills:

The actual CPO objects are all defined in an inline namespace called _Cpo, so for the <compare> CPOs that is std::_Cpo and for the others it is std::ranges::_Cpo.

When moving code between files, ensure that the relevant copyright notice corresponding to the code is also moved. For example, code from <bits/stl_algo.h> might be covered by the HP and SGI copyright notices, and so should not be moved to another header without those notices.

Extensions that libstdc++ relies on

Most of libstdc++ is written in portable C++, only using language features from the revision of the standard that introduced the library component. For example, std::forward_list was introduced in C++11 and so can use using-declarations and uniform initialization. std::variant was introduced in C++17, so can use 'if constexpr' and fold expressions. In a few cases we do make use of newer language features that are supported by GCC as a conforming extension. The list below tries to document these cases, but might be incomplete.

We also use the following extensions which are not defined in any revision of the C++ standard:

Doxygen

Try to add doxygen comments for everything, even if just a one-liner like:

/// A class that represents a calendar year.

Use the following Doxygen commands to add relevant details:

None: LibstdcxxHacking (last edited 2024-01-17 11:32:40 by JonathanWakely)