forked from OSchip/llvm-project
[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](af65856eec
) * [basic_string](6d9f750dec
) * [array](0ca8c0895c
) * [deque](dbb6f8a817
) * [forward_list](e076700b77
) * [list](4a227e582b
) * [vector](df8f754792
) * [queue/stack/priority_queue](5b8b8b5dce
) * [basic_regex](edd5e29cfe
) * [optional](f35b4bc395
) * [map/multimap](edfe8525de
) * [set/multiset](e20865c387
) * [unordered_set/unordered_multiset](296a80102a
) * [unordered_map/unordered_multimap](dfcd4384cb
) * [function](e1eabcdfad
) * [tuple](1308011e1b
) * [shared_ptr/weak_ptr](83564056d4
) 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
This commit is contained in:
parent
c9174f63b6
commit
f9f97cae82
|
@ -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.
|
||||
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
|
Can't render this file because it has a wrong number of fields in line 2.
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
// UNSUPPORTED: c++03
|
||||
|
||||
// <memory>
|
||||
// <scoped_allocator>
|
||||
|
||||
// template <class OuterAlloc, class... InnerAllocs>
|
||||
// class scoped_allocator_adaptor
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue