Skip to content

Commit 078651b

Browse files
authored
[libc++] Implement LWG3545: std::pointer_traits should be SFINAE-friendly. (llvm#65177)
See https://wg21.link/LWG3545 for background and details. Differential Revision: https://reviews.llvm.org/D158922
1 parent baf031a commit 078651b

File tree

9 files changed

+367
-184
lines changed

9 files changed

+367
-184
lines changed

libcxx/docs/Status/Cxx23Issues.csv

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,7 @@
190190
"`3118 <https://wg21.link/LWG3118>`__","``fpos`` equality comparison unspecified", "November 2022","","",""
191191
"`3177 <https://wg21.link/LWG3177>`__","Limit permission to specialize variable templates to program-defined types", "November 2022","|Nothing to do|","",""
192192
"`3515 <https://wg21.link/LWG3515>`__","§[stacktrace.basic.nonmem]: ``operator<<`` should be less templatized", "November 2022","","",""
193-
"`3545 <https://wg21.link/LWG3545>`__","``std::pointer_traits`` should be SFINAE-friendly", "November 2022","","",""
193+
"`3545 <https://wg21.link/LWG3545>`__","``std::pointer_traits`` should be SFINAE-friendly", "November 2022","|Complete|","18.0",""
194194
"`3569 <https://wg21.link/LWG3569>`__","``join_view`` fails to support ranges of ranges with non-default_initializable iterators", "November 2022","","","|ranges|"
195195
"`3594 <https://wg21.link/LWG3594>`__","``inout_ptr`` — inconsistent ``release()`` in destructor", "November 2022","","",""
196196
"`3597 <https://wg21.link/LWG3597>`__","Unsigned integer types don't model advanceable", "November 2022","","","|ranges|"

libcxx/include/__memory/pointer_traits.h

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ template <class _Tp>
3535
struct __has_element_type<_Tp, __void_t<typename _Tp::element_type> > : true_type {};
3636

3737
template <class _Ptr, bool = __has_element_type<_Ptr>::value>
38-
struct __pointer_traits_element_type;
38+
struct __pointer_traits_element_type {};
3939

4040
template <class _Ptr>
4141
struct __pointer_traits_element_type<_Ptr, true>
@@ -111,12 +111,14 @@ struct __pointer_traits_rebind<_Sp<_Tp, _Args...>, _Up, false>
111111
typedef _Sp<_Up, _Args...> type;
112112
};
113113

114+
template <class _Ptr, class = void>
115+
struct __pointer_traits_impl {};
116+
114117
template <class _Ptr>
115-
struct _LIBCPP_TEMPLATE_VIS pointer_traits
116-
{
117-
typedef _Ptr pointer;
118-
typedef typename __pointer_traits_element_type<pointer>::type element_type;
119-
typedef typename __pointer_traits_difference_type<pointer>::type difference_type;
118+
struct __pointer_traits_impl<_Ptr, __void_t<typename __pointer_traits_element_type<_Ptr>::type> > {
119+
typedef _Ptr pointer;
120+
typedef typename __pointer_traits_element_type<pointer>::type element_type;
121+
typedef typename __pointer_traits_difference_type<pointer>::type difference_type;
120122

121123
#ifndef _LIBCPP_CXX03_LANG
122124
template <class _Up> using rebind = typename __pointer_traits_rebind<pointer, _Up>::type;
@@ -133,6 +135,9 @@ struct _LIBCPP_TEMPLATE_VIS pointer_traits
133135
{return pointer::pointer_to(__r);}
134136
};
135137

138+
template <class _Ptr>
139+
struct _LIBCPP_TEMPLATE_VIS pointer_traits : __pointer_traits_impl<_Ptr> {};
140+
136141
template <class _Tp>
137142
struct _LIBCPP_TEMPLATE_VIS pointer_traits<_Tp*>
138143
{

libcxx/test/libcxx/iterators/iterator.requirements/iterator.concepts/iterator.concept.random.access/contiguous_iterator.verify.cpp

Lines changed: 0 additions & 54 deletions
This file was deleted.
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
// <memory>
10+
11+
// UNSUPPORTED: c++03, c++11, c++14, c++17
12+
13+
// template <class Ptr> constexpr auto to_address(const Ptr& p) noexcept;
14+
// Should not require a specialization of pointer_traits for Ptr.
15+
16+
#include <memory>
17+
#include <type_traits>
18+
#include <utility>
19+
20+
struct IntPtr {
21+
constexpr int* operator->() const { return ptr; }
22+
23+
int* ptr;
24+
};
25+
26+
template <class T, bool>
27+
struct TemplatedPtr {
28+
constexpr T* operator->() const { return ptr; }
29+
30+
T* ptr;
31+
};
32+
33+
template <template <class...> class Templ, class Ignore, class... Args>
34+
struct is_valid_expansion_impl : std::false_type {};
35+
36+
template <template <class...> class Templ, class... Args>
37+
struct is_valid_expansion_impl<Templ, decltype((void)Templ<Args...>{}, 0), Args...> : std::true_type {};
38+
39+
template <template <class...> class Templ, class... Args>
40+
using is_valid_expansion = is_valid_expansion_impl<Templ, int, Args...>;
41+
42+
template <class Ptr>
43+
using TestToAddressCall = decltype(std::to_address(std::declval<Ptr>()));
44+
45+
constexpr bool test() {
46+
int i = 0;
47+
48+
static_assert(std::to_address(IntPtr{nullptr}) == nullptr);
49+
static_assert(std::to_address(IntPtr{&i}) == &i);
50+
51+
bool b = false;
52+
53+
static_assert(std::to_address(TemplatedPtr<bool, true>{nullptr}) == nullptr);
54+
static_assert(std::to_address(TemplatedPtr<bool, true>{&b}) == &b);
55+
56+
static_assert(!is_valid_expansion<TestToAddressCall, int>::value);
57+
static_assert(is_valid_expansion<TestToAddressCall, IntPtr>::value);
58+
static_assert(is_valid_expansion<TestToAddressCall, TemplatedPtr<bool, true>>::value);
59+
60+
return true;
61+
}
62+
63+
int main(int, char**) {
64+
static_assert(test());
65+
return 0;
66+
}

libcxx/test/std/utilities/memory/pointer.traits/difference_type.pass.cpp

Lines changed: 0 additions & 28 deletions
This file was deleted.

libcxx/test/std/utilities/memory/pointer.traits/element_type.pass.cpp

Lines changed: 0 additions & 28 deletions
This file was deleted.

libcxx/test/std/utilities/memory/pointer.traits/pointer.pass.cpp

Lines changed: 0 additions & 35 deletions
This file was deleted.

libcxx/test/std/utilities/memory/pointer.traits/rebind.pass.cpp

Lines changed: 0 additions & 32 deletions
This file was deleted.

0 commit comments

Comments
 (0)