From f9f97cae82a05f54bed85581e57762ec2e26a057 Mon Sep 17 00:00:00 2001 From: Konstantin Varlamov Date: Thu, 28 Oct 2021 00:36:19 -0700 Subject: [PATCH] [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 --- libcxx/docs/Status/Cxx17.rst | 2 +- libcxx/docs/Status/Cxx20Issues.csv | 2 +- libcxx/include/scoped_allocator | 10 +++ libcxx/include/utility | 2 + libcxx/include/valarray | 7 ++ .../valarray.cons/deduct.pass.cpp | 73 +++++++++++++++++++ .../string.cons/iter_alloc_deduction.fail.cpp | 4 +- .../allocator.adaptor.cnstr/allocs.pass.cpp | 2 +- .../allocator.adaptor.cnstr/deduct.pass.cpp | 64 ++++++++++++++++ .../optional.object.ctor/deduct.pass.cpp | 33 ++++++++- 10 files changed, 191 insertions(+), 8 deletions(-) create mode 100644 libcxx/test/std/numerics/numarray/template.valarray/valarray.cons/deduct.pass.cpp create mode 100644 libcxx/test/std/utilities/allocator.adaptor/allocator.adaptor.cnstr/deduct.pass.cpp 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 ````, sequence containers, container adaptors and ```` 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 ```` 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 `__","Hash support for pmr::string and friends","Albuquerque","","" "`2979 `__","aligned_union should require complete object types","Albuquerque","|Complete|","" "`2980 `__","Cannot compare_exchange empty pointers","Albuquerque","","" -"`2981 `__","Remove redundant deduction guides from standard library","Albuquerque","","" +"`2981 `__","Remove redundant deduction guides from standard library","Albuquerque","|Nothing To Do|","" "`2982 `__","Making size_type consistent in associative container deduction guides","Albuquerque","","" "`2988 `__","Clause 32 cleanup missed one typename","Albuquerque","|Complete|","13.0" "`2993 `__","reference_wrapper 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 + scoped_allocator_adaptor(OuterAlloc, InnerAllocs...) + -> scoped_allocator_adaptor; + template bool operator==(const scoped_allocator_adaptor& a, @@ -649,6 +653,12 @@ private: template friend class __scoped_allocator_storage; }; +#if _LIBCPP_STD_VER > 14 +template + scoped_allocator_adaptor(_OuterAlloc, _InnerAllocs...) + -> scoped_allocator_adaptor<_OuterAlloc, _InnerAllocs...>; +#endif + template 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); // constexpr in C++20 }; +template pair(T1, T2) -> pair; + template bool operator==(const pair&, const pair&); // constexpr in C++14 template bool operator!=(const pair&, const pair&); // constexpr in C++14, removed in C++20 template bool operator< (const pair&, const pair&); // 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 valarray(const T(&)[cnt], size_t) -> valarray; + 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 +valarray(const _Tp(&)[_Size], size_t) -> valarray<_Tp>; +#endif + _LIBCPP_EXTERN_TEMPLATE(_LIBCPP_FUNC_VIS void valarray::resize(size_t, size_t)) template 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 + +// + +// template valarray(const T(&)[cnt], size_t) -> valarray; + +#include + +#include "test_macros.h" + +int main(int, char**) +{ + { + // From (initializer_list) + std::valarray v = {1, 2, 3, 4, 5}; + ASSERT_SAME_TYPE(decltype(v), std::valarray); + } + + { + // 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); + } + + { + // 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); + } + + { + // From (slice_array) + std::valarray v{1,2,3,4,5}; + std::valarray v2 = v[std::slice(2,3,1)]; + static_assert(std::is_same_v>); + } + + { + // From (gslice_array) + std::valarray v{1,2,3,4,5}; + std::valarray v2 = v[std::gslice(0, {5}, {1})]; + static_assert(std::is_same_v>); + } + + { + // From (mask_array) + std::valarray v = {1, 2, 3, 4, 5}; + std::valarray m = {true, false, true, false, true}; + std::valarray v2 = v[m]; + static_assert(std::is_same_v>); + } + + { + // From (indirect_array) + std::valarray v = {1, 2, 3, 4, 5}; + std::valarray i = {1, 2, 3}; + std::valarray v2 = v[i]; + static_assert(std::is_same_v>); + } + + 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 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{}}; // expected-error {{no viable constructor or deduction guide for deduction of template arguments of 'basic_string'}} + std::basic_string s1{NotAnIterator{}, NotAnIterator{}, std::allocator{}}; // expected-error {{no viable constructor or deduction guide for deduction of template arguments of 'basic_string'}} } { // Not an input iterator std::basic_string 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 -// +// // template // 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 + +// + +// template +// scoped_allocator_adaptor(_OuterAlloc, _InnerAllocs...) +// -> scoped_allocator_adaptor<_OuterAlloc, _InnerAllocs...>; + +#include + +#include "test_macros.h" +#include "allocators.h" + +int main(int, char**) +{ + // Deduct from (const OuterAlloc&). + { + typedef A1 OuterAlloc; + OuterAlloc outer(3); + std::scoped_allocator_adaptor a(outer); + ASSERT_SAME_TYPE(decltype(a), std::scoped_allocator_adaptor); + } + + // Deduct from (OuterAlloc&&). + { + typedef A1 OuterAlloc; + std::scoped_allocator_adaptor a(OuterAlloc(3)); + ASSERT_SAME_TYPE(decltype(a), std::scoped_allocator_adaptor); + } + + // Deduct from (const OuterAlloc&, const InnerAlloc&). + { + typedef A1 OuterAlloc; + typedef A2 InnerAlloc; + OuterAlloc outer(3); + InnerAlloc inner(4); + + std::scoped_allocator_adaptor a(outer, inner); + ASSERT_SAME_TYPE(decltype(a), std::scoped_allocator_adaptor); + } + + // Deduct from (const OuterAlloc&, const InnerAlloc1&, InnerAlloc2&&). + { + typedef A1 OuterAlloc; + typedef A2 InnerAlloc1; + typedef A2 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); + } + + 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>, ""); + ASSERT_SAME_TYPE(decltype(opt), std::optional); assert(static_cast(opt)); assert(*opt == 5); } @@ -33,16 +33,43 @@ int main(int, char**) { // optional(T) std::optional opt(A{}); - static_assert(std::is_same_v>, ""); + ASSERT_SAME_TYPE(decltype(opt), std::optional); assert(static_cast(opt)); } + { +// optional(const T&); + const int& source = 5; + std::optional opt(source); + ASSERT_SAME_TYPE(decltype(opt), std::optional); + assert(static_cast(opt)); + assert(*opt == 5); + } + + { +// optional(T*); + const int* source = nullptr; + std::optional opt(source); + ASSERT_SAME_TYPE(decltype(opt), std::optional); + assert(static_cast(opt)); + assert(*opt == nullptr); + } + + { +// optional(T[]); + int source[] = {1, 2, 3}; + std::optional opt(source); + ASSERT_SAME_TYPE(decltype(opt), std::optional); + assert(static_cast(opt)); + assert((*opt)[0] == 1); + } + // Test the implicit deduction guides { // optional(optional); std::optional source('A'); std::optional opt(source); - static_assert(std::is_same_v>, ""); + ASSERT_SAME_TYPE(decltype(opt), std::optional); assert(static_cast(opt) == static_cast(source)); assert(*opt == *source); }