[libcxx-commits] [libcxx] r363110 - Add documentation and tests for Clangs C++11 extensions in C++03.
Eric Fiselier via libcxx-commits
libcxx-commits at lists.llvm.org
Tue Jun 11 15:53:49 PDT 2019
Author: ericwf
Date: Tue Jun 11 15:53:49 2019
New Revision: 363110
URL: http://llvm.org/viewvc/llvm-project?rev=363110&view=rev
Log:
Add documentation and tests for Clangs C++11 extensions in C++03.
As we gear up to drop support for GCC in C++03, we should make clear
what our C++03 mode is, the C++11 extensions it provides,
and the C++11 extensions it depends on.
The section of this document discussing user-facing extensions has
been left blank while the community discusses new directions. For now
it's just a warning to users.
Additionally, the document contains examples of how these extensions
should be used and why. For example, using alias templates over class
templates.
Added:
libcxx/trunk/docs/DesignDocs/ExtendedCXX03Support.rst
libcxx/trunk/test/libcxx/minimal_cxx11_configuration.pass.cpp
Modified:
libcxx/trunk/docs/index.rst
Added: libcxx/trunk/docs/DesignDocs/ExtendedCXX03Support.rst
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/docs/DesignDocs/ExtendedCXX03Support.rst?rev=363110&view=auto
==============================================================================
--- libcxx/trunk/docs/DesignDocs/ExtendedCXX03Support.rst (added)
+++ libcxx/trunk/docs/DesignDocs/ExtendedCXX03Support.rst Tue Jun 11 15:53:49 2019
@@ -0,0 +1,118 @@
+=======================
+Extended C++03 Support
+=======================
+
+.. contents::
+ :local:
+
+Overview
+========
+
+libc++ is an implementation of the C++ standard library targeting C++11 or later.
+
+In C++03, the library implements the C++11 standard using C++11 language extensions provided
+by Clang.
+
+This document tracks the C++11 extensions libc++ requires, the C++11 extensions it provides,
+and how to write minimal C++11 inside libc++.
+
+Required C++11 Compiler Extensions
+==================================
+
+Clang provides a large subset of C++11 in C++03 as an extension. The features
+libc++ expects Clang to provide are:
+
+* Variadic templates.
+* RValue references and perfect forwarding.
+* Alias templates
+* defaulted and deleted Functions.
+* reference qualified Functions
+
+There are also features that Clang *does not* provide as an extension in C++03
+mode. These include:
+
+* ``constexpr`` and ``noexcept``
+* ``auto``
+* Trailing return types.
+* ``>>`` without a space.
+
+
+Provided C++11 Library Extensions
+=================================
+
+.. warning::
+ The C++11 extensions libc++ provides in C++03 are currently undergoing change. Existing extensions
+ may be removed in the future. New users are strongly discouraged depending on these extension
+ in new code.
+
+ This section will be updated once the libc++ developer community has further discussed the
+ future of C++03 with libc++.
+
+
+Using Minimal C++11 in libc++
+=============================
+
+This section is for developers submitting patches to libc++. It describes idioms that should be
+used in libc++ code, even in C++03, and the reasons behind them.
+
+
+Use Alias Templates over Class Templates
+----------------------------------------
+
+Alias templates should be used instead of class templates in metaprogramming. Unlike class templates,
+Alias templates do not produce a new instantiation every time they are used. This significantly
+decreases the amount of memory used by the compiler.
+
+For example, libc++ should not use ``add_const`` internally. Instead it should use an alias template
+like
+
+.. code-block:: cpp
+
+ template <class _Tp>
+ using _AddConst = const _Tp;
+
+Use Default Template Parameters for SFINAE
+------------------------------------------
+
+There are three places in a function declaration that SFINAE may occur: In the template parameter list,
+in the function parameter list, and in the return type. For example:
+
+.. code-block:: cpp
+
+ template <class _Tp, class _ = enable_if_t</*...*/ >
+ void foo(_Tp); // #1
+
+ template <class _Tp>
+ void bar(_Tp, enable_if_t</*...*/>* = nullptr); // # 2
+
+ template <class _Tp>
+ enable_if_t</*...*/> baz(_Tp); // # 3
+
+Using default template parameters for SFINAE (#1) should always be prefered.
+
+Option #2 has two problems. First, users can observe and accidentally pass values to the SFINAE
+function argument. Second, the default arguement creates a live variable, which causes debug
+information to be emitted containing the text of the SFINAE.
+
+Option #3 can also cause more debug information to be emitted than is needed, because the function
+return type will appear in the debug information.
+
+Use ``unique_ptr`` when allocating memory
+------------------------------------------
+
+The standard library often needs to allocate memory and then construct a user type in it.
+If the users constructor throws, the library needs to deallocate that memory. The idiomatic way to
+achieve this is with ``unique_ptr``.
+
+``__builtin_new_allocator`` is an example of this idiom. Example usage would look like:
+
+.. code-block:: cpp
+
+ template <class T>
+ T* __create() {
+ using _UniquePtr = unique_ptr<void*, __default_new_allocator::__default_new_deleter>;
+ _UniquePtr __p = __default_new_allocator::__allocate_bytes(sizeof(T), alignof(T));
+ T* __res = ::new(__p.get()) T();
+ (void)__p.release();
+ return __res;
+ }
Modified: libcxx/trunk/docs/index.rst
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/docs/index.rst?rev=363110&r1=363109&r2=363110&view=diff
==============================================================================
--- libcxx/trunk/docs/index.rst (original)
+++ libcxx/trunk/docs/index.rst Tue Jun 11 15:53:49 2019
@@ -142,6 +142,7 @@ Design Documents
DesignDocs/ThreadingSupportAPI
DesignDocs/FileTimeType
DesignDocs/FeatureTestMacros
+ DesignDocs/ExtendedCXX03Support
* `<atomic> design <http://libcxx.llvm.org/atomic_design.html>`_
* `<type_traits> design <http://libcxx.llvm.org/type_traits_design.html>`_
Added: libcxx/trunk/test/libcxx/minimal_cxx11_configuration.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/libcxx/minimal_cxx11_configuration.pass.cpp?rev=363110&view=auto
==============================================================================
--- libcxx/trunk/test/libcxx/minimal_cxx11_configuration.pass.cpp (added)
+++ libcxx/trunk/test/libcxx/minimal_cxx11_configuration.pass.cpp Tue Jun 11 15:53:49 2019
@@ -0,0 +1,135 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+
+// Test the set of C++11 features that Clang provides as an extension in C++03 mode.
+// The language features we expect are:
+//
+// 1. rvalue references (and perfect forwarding)
+// 2. variadic templates
+// 3. alias templates
+// 4. defaulted and deleted functions.
+// 5. default values for non-type template parameters.
+//
+// Some features we don't get and can't be used in extended C++03 mode:
+//
+// 1. noexcept and constexpr
+// 2. Two closing '>' without a space.
+
+#ifdef __clang__
+#pragma clang diagnostic ignored "-Wc++11-extensions"
+#endif
+
+#include <type_traits>
+#include <cassert>
+
+// Equals delete and default are allowed in minimal C++03 mode.
+namespace test_eq_delete_and_default {
+void t1() = delete;
+struct T2 {
+ T2() = default;
+ T2(T2 const&) = delete;
+};
+}
+
+namespace alias_templates {
+template <class T>
+using X = T;
+static_assert((std::is_same<X<int>, int>::value), "");
+}
+
+namespace variadics_templates {
+template <class ...Args>
+int t1(Args...) {
+ return sizeof...(Args);
+}
+void test() {
+ assert(t1() == 0);
+ assert(t1(42) == 1);
+ assert(t1(1, 2, 3) == 3);
+}
+}
+
+namespace rvalue_references_move_semantics {
+struct T {
+ T() : moved(0) {}
+ T(T const& other) : moved(other.moved) {}
+ T(T&& other) : moved(other.moved) { ++moved; other.moved = -1; }
+ int moved;
+};
+void f(T o, int expect_moved) { assert(o.moved == expect_moved); }
+void test() {
+ {
+ T t;
+ assert(t.moved == 0);
+ T t2(static_cast<T&&>(t));
+ assert(t2.moved == 1);
+ assert(t.moved == -1);
+ }
+ {
+ T t;
+ f(t, 0);
+ f(static_cast<T&&>(t), 1);
+ }
+}
+}
+
+namespace rvalue_references_perfect_forwarding {
+template <class Expect, class T>
+void f(T&&) {
+ static_assert((std::is_same<Expect, T&&>::value), "");
+}
+void test() {
+ int x = 42;
+ f<int&>(x);
+ f<int&&>(42);
+ f<int&&>(static_cast<int&&>(x));
+}
+}
+
+namespace default_values_for_nttp {
+template <int I = 42>
+void f() { assert(I == 42); }
+void test() {
+ f();
+}
+}
+
+namespace reference_qualified_functions {
+struct T {
+ T() : lvalue_called(0), rvalue_called(0) {}
+ void foo() const & { lvalue_called++; }
+ void foo() && { rvalue_called++; }
+ mutable int lvalue_called;
+ int rvalue_called;
+};
+
+void test() {
+ {
+ T t;
+ t.foo();
+ assert(t.lvalue_called == 1);
+ assert(t.rvalue_called == 0);
+ }
+ {
+ T t;
+ static_cast<T&&>(t).foo();
+ assert(t.lvalue_called == 0);
+ assert(t.rvalue_called == 1);
+ }
+}
+}
+
+int main(int, char**) {
+ variadics_templates::test();
+ rvalue_references_move_semantics::test();
+ rvalue_references_perfect_forwarding::test();
+ default_values_for_nttp::test();
+ reference_qualified_functions::test();
+ return 0;
+}
More information about the libcxx-commits
mailing list