[libcxx-commits] [libcxx] f9f97ca - [libc++] P0433R2: add the remaining deduction guides.

Konstantin Varlamov via libcxx-commits libcxx-commits at lists.llvm.org
Thu Oct 28 11:10:10 PDT 2021


Author: Konstantin Varlamov
Date: 2021-10-28T11:09:51-07:00
New Revision: f9f97cae82a05f54bed85581e57762ec2e26a057

URL: https://github.com/llvm/llvm-project/commit/f9f97cae82a05f54bed85581e57762ec2e26a057
DIFF: https://github.com/llvm/llvm-project/commit/f9f97cae82a05f54bed85581e57762ec2e26a057.diff

LOG: [libc++] P0433R2: add the remaining deduction guides.

Add deduction guides to `valarray` and `scoped_allocator_adaptor`. This largely
finishes implementation of the paper:

* deduction guides for other classes mentioned in the paper were
  implemented previously (see the list below);
* deduction guides for several classes contained in the proposal
  (`reference_wrapper`, `lock_guard`, `scoped_lock`, `unique_lock`,
  `shared_lock`) were removed by [LWG2981](https://wg21.link/LWG2981).

Also add deduction guides to the synopsis for the few classes (e.g. `pair`)
where they were missing.

The only part of the paper that isn't fully implemented after this patch is
making sure certain deduction guides don't participate in overload resolution
when given incorrect template parameters.

List of significant commits implementing the other parts of P0433 (omitting some
minor fixes):

* [pair](https://github.com/llvm/llvm-project/commit/af65856eec160d163c764faad250d93357be7c83)
* [basic_string](https://github.com/llvm/llvm-project/commit/6d9f750dec29e8ae5366092e64cd343dae2c7464)
* [array](https://github.com/llvm/llvm-project/commit/0ca8c0895c6034615593c295dd955f29b25bf3d4)
* [deque](https://github.com/llvm/llvm-project/commit/dbb6f8a8179b0604e25707b5c1b72be6164f62d9)
* [forward_list](https://github.com/llvm/llvm-project/commit/e076700b7786959206acef136ecf05d54078e4e1)
* [list](https://github.com/llvm/llvm-project/commit/4a227e582b2f13880ea049b29988a37a0f7c0742)
* [vector](https://github.com/llvm/llvm-project/commit/df8f75479278d5ce16eede342ceb5ba2fd71460b)
* [queue/stack/priority_queue](https://github.com/llvm/llvm-project/commit/5b8b8b5dce587f1e5a4a31cc24f09b18bd53ff9a)
* [basic_regex](https://github.com/llvm/llvm-project/commit/edd5e29cfe9f67ec8e7e0eda12eb05e616fdeebc)
* [optional](https://github.com/llvm/llvm-project/commit/f35b4bc3954f3b01051fc0848535ff784809e9e2)
* [map/multimap](https://github.com/llvm/llvm-project/commit/edfe8525de1f7278f4754f2bffd47b13ec291a17)
* [set/multiset](https://github.com/llvm/llvm-project/commit/e20865c387e09ea0ebd5add15c762cd5271ff65f)
* [unordered_set/unordered_multiset](https://github.com/llvm/llvm-project/commit/296a80102a9b72c3eda80558fb78a3ed8849b341)
* [unordered_map/unordered_multimap](https://github.com/llvm/llvm-project/commit/dfcd4384cbcac0eeb7e5cbce350f875ba4da79d5)
* [function](https://github.com/llvm/llvm-project/commit/e1eabcdfad89f67ae575b0c86aa4a72d277378b4)
* [tuple](https://github.com/llvm/llvm-project/commit/1308011e1b5c5382281a63dd4191a1784f8d2295)
* [shared_ptr/weak_ptr](https://github.com/llvm/llvm-project/commit/83564056d4b186c9fcf016cdbb388755009f7b5a)

Additional notes:
* It was revision 2 of the paper that was voted into the Standard.
  P0433R3 is a separate paper that is not part of the Standard.
* The paper also mandates removing several `make_*_searcher` functions
  (e.g. `make_boyer_moore_searcher`) which are currently not implemented
  (except in `experimental/`).
* The `__cpp_lib_deduction_guides` feature test macro from the paper was
  accidentally omitted from the Standard.

Differential Revision: https://reviews.llvm.org/D112510

Added: 
    libcxx/test/std/numerics/numarray/template.valarray/valarray.cons/deduct.pass.cpp
    libcxx/test/std/utilities/allocator.adaptor/allocator.adaptor.cnstr/deduct.pass.cpp

Modified: 
    libcxx/docs/Status/Cxx17.rst
    libcxx/docs/Status/Cxx20Issues.csv
    libcxx/include/scoped_allocator
    libcxx/include/utility
    libcxx/include/valarray
    libcxx/test/std/strings/basic.string/string.cons/iter_alloc_deduction.fail.cpp
    libcxx/test/std/utilities/allocator.adaptor/allocator.adaptor.cnstr/allocs.pass.cpp
    libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/deduct.pass.cpp

Removed: 
    


################################################################################
diff  --git a/libcxx/docs/Status/Cxx17.rst b/libcxx/docs/Status/Cxx17.rst
index 05f97101b1bd..1131950820f2 100644
--- a/libcxx/docs/Status/Cxx17.rst
+++ b/libcxx/docs/Status/Cxx17.rst
@@ -40,7 +40,7 @@ Paper Status
 
 .. note::
 
-   .. [#note-P0433] P0433: So far, only the ``<string>``, sequence containers, container adaptors and ``<regex>`` portions of P0433 have been implemented.
+   .. [#note-P0433] P0433: The only part not fully implemented is the requirement that certain deduction guides should not participate in overload resolution when given incorrect template arguments.
    .. [#note-P0607] P0607: The parts of P0607 that are not done are the ``<regex>`` bits.
 
 

diff  --git a/libcxx/docs/Status/Cxx20Issues.csv b/libcxx/docs/Status/Cxx20Issues.csv
index 4f62a9a9d5e8..3962cd119550 100644
--- a/libcxx/docs/Status/Cxx20Issues.csv
+++ b/libcxx/docs/Status/Cxx20Issues.csv
@@ -32,7 +32,7 @@
 "`2978 <https://wg21.link/LWG2978>`__","Hash support for pmr::string and friends","Albuquerque","",""
 "`2979 <https://wg21.link/LWG2979>`__","aligned_union should require complete object types","Albuquerque","|Complete|",""
 "`2980 <https://wg21.link/LWG2980>`__","Cannot compare_exchange empty pointers","Albuquerque","",""
-"`2981 <https://wg21.link/LWG2981>`__","Remove redundant deduction guides from standard library","Albuquerque","",""
+"`2981 <https://wg21.link/LWG2981>`__","Remove redundant deduction guides from standard library","Albuquerque","|Nothing To Do|",""
 "`2982 <https://wg21.link/LWG2982>`__","Making size_type consistent in associative container deduction guides","Albuquerque","",""
 "`2988 <https://wg21.link/LWG2988>`__","Clause 32 cleanup missed one typename","Albuquerque","|Complete|","13.0"
 "`2993 <https://wg21.link/LWG2993>`__","reference_wrapper<T> conversion from T&&","Albuquerque","|Complete|","13.0"

diff  --git a/libcxx/include/scoped_allocator b/libcxx/include/scoped_allocator
index dc24d30b510f..5c2aeb7cf719 100644
--- a/libcxx/include/scoped_allocator
+++ b/libcxx/include/scoped_allocator
@@ -91,6 +91,10 @@ public:
     scoped_allocator_adaptor select_on_container_copy_construction() const noexcept;
 };
 
+template<class OuterAlloc, class... InnerAllocs>
+    scoped_allocator_adaptor(OuterAlloc, InnerAllocs...)
+        -> scoped_allocator_adaptor<OuterAlloc, InnerAllocs...>;
+
 template <class OuterA1, class OuterA2, class... InnerAllocs>
     bool
     operator==(const scoped_allocator_adaptor<OuterA1, InnerAllocs...>& a,
@@ -649,6 +653,12 @@ private:
     template <class...> friend class __scoped_allocator_storage;
 };
 
+#if _LIBCPP_STD_VER > 14
+template<class _OuterAlloc, class... _InnerAllocs>
+    scoped_allocator_adaptor(_OuterAlloc, _InnerAllocs...)
+        -> scoped_allocator_adaptor<_OuterAlloc, _InnerAllocs...>;
+#endif
+
 template <class _OuterA1, class _OuterA2>
 inline _LIBCPP_INLINE_VISIBILITY
 bool

diff  --git a/libcxx/include/utility b/libcxx/include/utility
index 7d021d958029..f8b954fc4544 100644
--- a/libcxx/include/utility
+++ b/libcxx/include/utility
@@ -95,6 +95,8 @@ struct pair
                                 is_nothrow_swappable_v<T2>);                     // constexpr in C++20
 };
 
+template<class T1, class T2> pair(T1, T2) -> pair<T1, T2>;
+
 template <class T1, class T2> bool operator==(const pair<T1,T2>&, const pair<T1,T2>&); // constexpr in C++14
 template <class T1, class T2> bool operator!=(const pair<T1,T2>&, const pair<T1,T2>&); // constexpr in C++14, removed in C++20
 template <class T1, class T2> bool operator< (const pair<T1,T2>&, const pair<T1,T2>&); // constexpr in C++14, removed in C++20

diff  --git a/libcxx/include/valarray b/libcxx/include/valarray
index 9a64839bd6da..7364881a9cbe 100644
--- a/libcxx/include/valarray
+++ b/libcxx/include/valarray
@@ -105,6 +105,8 @@ public:
     void resize(size_t n, value_type x = value_type());
 };
 
+template<class T, size_t cnt> valarray(const T(&)[cnt], size_t) -> valarray<T>;
+
 class slice
 {
 public:
@@ -1081,6 +1083,11 @@ private:
     valarray& __assign_range(const value_type* __f, const value_type* __l);
 };
 
+#if _LIBCPP_STD_VER > 14
+template<class _Tp, size_t _Size>
+valarray(const _Tp(&)[_Size], size_t) -> valarray<_Tp>;
+#endif
+
 _LIBCPP_EXTERN_TEMPLATE(_LIBCPP_FUNC_VIS void valarray<size_t>::resize(size_t, size_t))
 
 template <class _Op, class _Tp>

diff  --git a/libcxx/test/std/numerics/numarray/template.valarray/valarray.cons/deduct.pass.cpp b/libcxx/test/std/numerics/numarray/template.valarray/valarray.cons/deduct.pass.cpp
new file mode 100644
index 000000000000..80ac2ae0fd63
--- /dev/null
+++ b/libcxx/test/std/numerics/numarray/template.valarray/valarray.cons/deduct.pass.cpp
@@ -0,0 +1,73 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14
+
+// <valarray>
+
+// template<class T, size_t cnt> valarray(const T(&)[cnt], size_t) -> valarray<T>;
+
+#include <valarray>
+
+#include "test_macros.h"
+
+int main(int, char**)
+{
+    {
+        // From (initializer_list<T>)
+        std::valarray v = {1, 2, 3, 4, 5};
+        ASSERT_SAME_TYPE(decltype(v), std::valarray<int>);
+    }
+
+    {
+        // From (const T(&)[N], size_t)
+        long a[] = {1, 2, 3, 4, 5};
+        std::valarray v(a, 5);
+        ASSERT_SAME_TYPE(decltype(v), std::valarray<long>);
+    }
+
+    {
+        // From (const T&, size_t)
+        long a[] = {1, 2, 3, 4, 5};
+        std::valarray v(&a[0], 5);
+        // Surprising but true.
+        ASSERT_SAME_TYPE(decltype(v), std::valarray<long*>);
+    }
+
+    {
+        // From (slice_array<T>)
+        std::valarray<long> v{1,2,3,4,5};
+        std::valarray v2 = v[std::slice(2,3,1)];
+        static_assert(std::is_same_v<decltype(v2), std::valarray<long>>);
+    }
+
+    {
+        // From (gslice_array<T>)
+        std::valarray<long> v{1,2,3,4,5};
+        std::valarray v2 = v[std::gslice(0, {5}, {1})];
+        static_assert(std::is_same_v<decltype(v2), std::valarray<long>>);
+    }
+
+    {
+        // From (mask_array<T>)
+        std::valarray<long> v = {1, 2, 3, 4, 5};
+        std::valarray<bool> m = {true, false, true, false, true};
+        std::valarray v2 = v[m];
+        static_assert(std::is_same_v<decltype(v2), std::valarray<long>>);
+    }
+
+    {
+        // From (indirect_array<T>)
+        std::valarray<long> v = {1, 2, 3, 4, 5};
+        std::valarray<size_t> i = {1, 2, 3};
+        std::valarray v2 = v[i];
+        static_assert(std::is_same_v<decltype(v2), std::valarray<long>>);
+    }
+
+  return 0;
+}

diff  --git a/libcxx/test/std/strings/basic.string/string.cons/iter_alloc_deduction.fail.cpp b/libcxx/test/std/strings/basic.string/string.cons/iter_alloc_deduction.fail.cpp
index 5f4fd060c866..4ab4189d3e4c 100644
--- a/libcxx/test/std/strings/basic.string/string.cons/iter_alloc_deduction.fail.cpp
+++ b/libcxx/test/std/strings/basic.string/string.cons/iter_alloc_deduction.fail.cpp
@@ -28,7 +28,7 @@
 
 #include "test_macros.h"
 
-class NotAnItertor {};
+class NotAnIterator {};
 
 template <typename T>
 struct NotAnAllocator { typedef T value_type; };
@@ -36,7 +36,7 @@ struct NotAnAllocator { typedef T value_type; };
 int main(int, char**)
 {
     { // Not an iterator at all
-    std::basic_string s1{NotAnItertor{}, NotAnItertor{}, std::allocator<char>{}}; // expected-error {{no viable constructor or deduction guide for deduction of template arguments of 'basic_string'}}
+    std::basic_string s1{NotAnIterator{}, NotAnIterator{}, std::allocator<char>{}}; // expected-error {{no viable constructor or deduction guide for deduction of template arguments of 'basic_string'}}
     }
     { // Not an input iterator
     std::basic_string<char16_t> s0;

diff  --git a/libcxx/test/std/utilities/allocator.adaptor/allocator.adaptor.cnstr/allocs.pass.cpp b/libcxx/test/std/utilities/allocator.adaptor/allocator.adaptor.cnstr/allocs.pass.cpp
index 09d28ceff46a..2a9d7052eb65 100644
--- a/libcxx/test/std/utilities/allocator.adaptor/allocator.adaptor.cnstr/allocs.pass.cpp
+++ b/libcxx/test/std/utilities/allocator.adaptor/allocator.adaptor.cnstr/allocs.pass.cpp
@@ -8,7 +8,7 @@
 
 // UNSUPPORTED: c++03
 
-// <memory>
+// <scoped_allocator>
 
 // template <class OuterAlloc, class... InnerAllocs>
 //   class scoped_allocator_adaptor

diff  --git a/libcxx/test/std/utilities/allocator.adaptor/allocator.adaptor.cnstr/deduct.pass.cpp b/libcxx/test/std/utilities/allocator.adaptor/allocator.adaptor.cnstr/deduct.pass.cpp
new file mode 100644
index 000000000000..2e1272105215
--- /dev/null
+++ b/libcxx/test/std/utilities/allocator.adaptor/allocator.adaptor.cnstr/deduct.pass.cpp
@@ -0,0 +1,64 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14
+
+// <scoped_allocator>
+
+// template<class _OuterAlloc, class... _InnerAllocs>
+//     scoped_allocator_adaptor(_OuterAlloc, _InnerAllocs...)
+//         -> scoped_allocator_adaptor<_OuterAlloc, _InnerAllocs...>;
+
+#include <scoped_allocator>
+
+#include "test_macros.h"
+#include "allocators.h"
+
+int main(int, char**)
+{
+    // Deduct from (const OuterAlloc&).
+    {
+        typedef A1<int> OuterAlloc;
+        OuterAlloc outer(3);
+        std::scoped_allocator_adaptor a(outer);
+        ASSERT_SAME_TYPE(decltype(a), std::scoped_allocator_adaptor<OuterAlloc>);
+    }
+
+    // Deduct from (OuterAlloc&&).
+    {
+        typedef A1<int> OuterAlloc;
+        std::scoped_allocator_adaptor a(OuterAlloc(3));
+        ASSERT_SAME_TYPE(decltype(a), std::scoped_allocator_adaptor<OuterAlloc>);
+    }
+
+    // Deduct from (const OuterAlloc&, const InnerAlloc&).
+    {
+        typedef A1<int> OuterAlloc;
+        typedef A2<int> InnerAlloc;
+        OuterAlloc outer(3);
+        InnerAlloc inner(4);
+
+        std::scoped_allocator_adaptor a(outer, inner);
+        ASSERT_SAME_TYPE(decltype(a), std::scoped_allocator_adaptor<OuterAlloc, InnerAlloc>);
+    }
+
+    // Deduct from (const OuterAlloc&, const InnerAlloc1&, InnerAlloc2&&).
+    {
+        typedef A1<int> OuterAlloc;
+        typedef A2<int> InnerAlloc1;
+        typedef A2<float> InnerAlloc2;
+        OuterAlloc outer(3);
+        InnerAlloc1 inner(4);
+
+        std::scoped_allocator_adaptor a(outer, inner, InnerAlloc2(5));
+        ASSERT_SAME_TYPE(
+            decltype(a), std::scoped_allocator_adaptor<OuterAlloc, InnerAlloc1, InnerAlloc2>);
+    }
+
+  return 0;
+}

diff  --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/deduct.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/deduct.pass.cpp
index f69427bd91ab..9bfde5abaa9a 100644
--- a/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/deduct.pass.cpp
+++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/deduct.pass.cpp
@@ -25,7 +25,7 @@ int main(int, char**)
     {
 //  optional(T)
     std::optional opt(5);
-    static_assert(std::is_same_v<decltype(opt), std::optional<int>>, "");
+    ASSERT_SAME_TYPE(decltype(opt), std::optional<int>);
     assert(static_cast<bool>(opt));
     assert(*opt == 5);
     }
@@ -33,16 +33,43 @@ int main(int, char**)
     {
 //  optional(T)
     std::optional opt(A{});
-    static_assert(std::is_same_v<decltype(opt), std::optional<A>>, "");
+    ASSERT_SAME_TYPE(decltype(opt), std::optional<A>);
     assert(static_cast<bool>(opt));
     }
 
+    {
+//  optional(const T&);
+    const int& source = 5;
+    std::optional opt(source);
+    ASSERT_SAME_TYPE(decltype(opt), std::optional<int>);
+    assert(static_cast<bool>(opt));
+    assert(*opt == 5);
+    }
+
+    {
+//  optional(T*);
+    const int* source = nullptr;
+    std::optional opt(source);
+    ASSERT_SAME_TYPE(decltype(opt), std::optional<const int*>);
+    assert(static_cast<bool>(opt));
+    assert(*opt == nullptr);
+    }
+
+    {
+//  optional(T[]);
+    int source[] = {1, 2, 3};
+    std::optional opt(source);
+    ASSERT_SAME_TYPE(decltype(opt), std::optional<int*>);
+    assert(static_cast<bool>(opt));
+    assert((*opt)[0] == 1);
+    }
+
 //  Test the implicit deduction guides
     {
 //  optional(optional);
     std::optional<char> source('A');
     std::optional opt(source);
-    static_assert(std::is_same_v<decltype(opt), std::optional<char>>, "");
+    ASSERT_SAME_TYPE(decltype(opt), std::optional<char>);
     assert(static_cast<bool>(opt) == static_cast<bool>(source));
     assert(*opt == *source);
     }


        


More information about the libcxx-commits mailing list