Home | History | Annotate | Line # | Download | only in DesignDocs
      1  1.1  joerg =======================
      2  1.1  joerg Extended C++03 Support
      3  1.1  joerg =======================
      4  1.1  joerg 
      5  1.1  joerg .. contents::
      6  1.1  joerg    :local:
      7  1.1  joerg 
      8  1.1  joerg Overview
      9  1.1  joerg ========
     10  1.1  joerg 
     11  1.1  joerg libc++ is an implementation of the C++ standard library targeting C++11 or later.
     12  1.1  joerg 
     13  1.1  joerg In C++03, the library implements the C++11 standard using C++11 language extensions provided
     14  1.1  joerg by Clang.
     15  1.1  joerg 
     16  1.1  joerg This document tracks the C++11 extensions libc++ requires, the C++11 extensions it provides,
     17  1.1  joerg and how to write minimal C++11 inside libc++.
     18  1.1  joerg 
     19  1.1  joerg Required C++11 Compiler Extensions
     20  1.1  joerg ==================================
     21  1.1  joerg 
     22  1.1  joerg Clang provides a large subset of C++11 in C++03 as an extension. The features
     23  1.1  joerg libc++ expects Clang  to provide are:
     24  1.1  joerg 
     25  1.1  joerg * Variadic templates.
     26  1.1  joerg * RValue references and perfect forwarding.
     27  1.1  joerg * Alias templates
     28  1.1  joerg * defaulted and deleted Functions.
     29  1.1  joerg * reference qualified Functions
     30  1.1  joerg 
     31  1.1  joerg There are also features that Clang *does not* provide as an extension in C++03
     32  1.1  joerg mode. These include:
     33  1.1  joerg 
     34  1.1  joerg * ``constexpr`` and ``noexcept``
     35  1.1  joerg * ``auto``
     36  1.1  joerg *  Trailing return types.
     37  1.1  joerg * ``>>`` without a space.
     38  1.1  joerg 
     39  1.1  joerg 
     40  1.1  joerg Provided C++11 Library Extensions
     41  1.1  joerg =================================
     42  1.1  joerg 
     43  1.1  joerg .. warning::
     44  1.1  joerg   The C++11 extensions libc++ provides in C++03 are currently undergoing change. Existing extensions
     45  1.1  joerg   may be removed in the future. New users are strongly discouraged depending on these extension
     46  1.1  joerg   in new code.
     47  1.1  joerg 
     48  1.1  joerg   This section will be updated once the libc++ developer community has further discussed the
     49  1.1  joerg   future of C++03 with libc++.
     50  1.1  joerg 
     51  1.1  joerg 
     52  1.1  joerg Using Minimal C++11 in libc++
     53  1.1  joerg =============================
     54  1.1  joerg 
     55  1.1  joerg This section is for developers submitting patches to libc++. It describes idioms that should be
     56  1.1  joerg used in libc++ code, even in C++03, and the reasons behind them.
     57  1.1  joerg 
     58  1.1  joerg 
     59  1.1  joerg Use Alias Templates over Class Templates
     60  1.1  joerg ----------------------------------------
     61  1.1  joerg 
     62  1.1  joerg Alias templates should be used instead of class templates in metaprogramming. Unlike class templates,
     63  1.1  joerg Alias templates do not produce a new instantiation every time they are used. This significantly
     64  1.1  joerg decreases the amount of memory used by the compiler.
     65  1.1  joerg 
     66  1.1  joerg For example, libc++ should not use ``add_const`` internally. Instead it should use an alias template
     67  1.1  joerg like
     68  1.1  joerg 
     69  1.1  joerg .. code-block:: cpp
     70  1.1  joerg 
     71  1.1  joerg   template <class _Tp>
     72  1.1  joerg   using _AddConst = const _Tp;
     73  1.1  joerg 
     74  1.1  joerg Use Default Template Parameters for SFINAE
     75  1.1  joerg ------------------------------------------
     76  1.1  joerg 
     77  1.1  joerg There are three places in a function declaration that SFINAE may occur: In the template parameter list,
     78  1.1  joerg in the function parameter list, and in the return type. For example:
     79  1.1  joerg 
     80  1.1  joerg .. code-block:: cpp
     81  1.1  joerg 
     82  1.1  joerg   template <class _Tp, class _ = enable_if_t</*...*/ >
     83  1.1  joerg   void foo(_Tp); // #1
     84  1.1  joerg 
     85  1.1  joerg   template <class _Tp>
     86  1.1  joerg   void bar(_Tp, enable_if_t</*...*/>* = nullptr); // # 2
     87  1.1  joerg 
     88  1.1  joerg   template <class _Tp>
     89  1.1  joerg   enable_if_t</*...*/> baz(_Tp); // # 3
     90  1.1  joerg 
     91  1.1  joerg Using default template parameters for SFINAE (#1) should always be prefered.
     92  1.1  joerg 
     93  1.1  joerg Option #2 has two problems. First, users can observe and accidentally pass values to the SFINAE
     94  1.1  joerg function argument. Second, the default arguement creates a live variable, which causes debug
     95  1.1  joerg information to be emitted containing the text of the SFINAE.
     96  1.1  joerg 
     97  1.1  joerg Option #3 can also cause more debug information to be emitted than is needed, because the function
     98  1.1  joerg return type will appear in the debug information.
     99  1.1  joerg 
    100  1.1  joerg Use ``unique_ptr`` when allocating memory
    101  1.1  joerg ------------------------------------------
    102  1.1  joerg 
    103  1.1  joerg The standard library often needs to allocate memory and then construct a user type in it.
    104  1.1  joerg If the users constructor throws, the library needs to deallocate that memory. The idiomatic way to
    105  1.1  joerg achieve this is with ``unique_ptr``.
    106  1.1  joerg 
    107  1.1  joerg ``__builtin_new_allocator`` is an example of this idiom. Example usage would look like:
    108  1.1  joerg 
    109  1.1  joerg .. code-block:: cpp
    110  1.1  joerg 
    111  1.1  joerg   template <class T>
    112  1.1  joerg   T* __create() {
    113  1.1  joerg     using _UniquePtr = unique_ptr<void*, __default_new_allocator::__default_new_deleter>;
    114  1.1  joerg     _UniquePtr __p = __default_new_allocator::__allocate_bytes(sizeof(T), alignof(T));
    115  1.1  joerg     T* __res = ::new(__p.get()) T();
    116  1.1  joerg     (void)__p.release();
    117  1.1  joerg     return __res;
    118  1.1  joerg   }
    119