Skip to content

Commit ddc6279

Browse files
authored
[libc++] Simplify the implementation of __is_referenceable (#130043)
The `__is_referenceable` builtin has been removed from Clang, since all its uses have been replaced by builtins themselves. This trait only exists for GCC compatibility and to word around some issues in the other traits. The non-builtin implementation has been refactored to use variable templates instead, making the implementation much simpler.
1 parent 66531c9 commit ddc6279

File tree

8 files changed

+211
-223
lines changed

8 files changed

+211
-223
lines changed

libcxx/include/__type_traits/add_lvalue_reference.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ using __add_lvalue_reference_t _LIBCPP_NODEBUG = __add_lvalue_reference(_Tp);
2525

2626
#else
2727

28-
template <class _Tp, bool = __libcpp_is_referenceable<_Tp>::value>
28+
template <class _Tp, bool = __is_referenceable_v<_Tp>>
2929
struct __add_lvalue_reference_impl {
3030
using type _LIBCPP_NODEBUG = _Tp;
3131
};

libcxx/include/__type_traits/add_pointer.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ template <class _Tp>
2626
using __add_pointer_t _LIBCPP_NODEBUG = __add_pointer(_Tp);
2727

2828
#else
29-
template <class _Tp, bool = __libcpp_is_referenceable<_Tp>::value || is_void<_Tp>::value>
29+
template <class _Tp, bool = __is_referenceable_v<_Tp> || is_void<_Tp>::value>
3030
struct __add_pointer_impl {
3131
using type _LIBCPP_NODEBUG = __libcpp_remove_reference_t<_Tp>*;
3232
};

libcxx/include/__type_traits/add_rvalue_reference.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ using __add_rvalue_reference_t _LIBCPP_NODEBUG = __add_rvalue_reference(_Tp);
2525

2626
#else
2727

28-
template <class _Tp, bool = __libcpp_is_referenceable<_Tp>::value>
28+
template <class _Tp, bool = __is_referenceable_v<_Tp> >
2929
struct __add_rvalue_reference_impl {
3030
using type _LIBCPP_NODEBUG = _Tp;
3131
};

libcxx/include/__type_traits/decay.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ struct _LIBCPP_TEMPLATE_VIS decay {
5555
using _Up _LIBCPP_NODEBUG = __libcpp_remove_reference_t<_Tp>;
5656

5757
public:
58-
using type _LIBCPP_NODEBUG = typename __decay<_Up, __libcpp_is_referenceable<_Up>::value>::type;
58+
using type _LIBCPP_NODEBUG = typename __decay<_Up, __is_referenceable_v<_Up> >::type;
5959
};
6060

6161
template <class _Tp>

libcxx/include/__type_traits/is_referenceable.h

Lines changed: 4 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -10,31 +10,19 @@
1010
#define _LIBCPP___TYPE_TRAITS_IS_REFERENCEABLE_H
1111

1212
#include <__config>
13-
#include <__type_traits/integral_constant.h>
14-
#include <__type_traits/is_same.h>
13+
#include <__type_traits/void_t.h>
1514

1615
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
1716
# pragma GCC system_header
1817
#endif
1918

2019
_LIBCPP_BEGIN_NAMESPACE_STD
2120

22-
#if __has_builtin(__is_referenceable)
23-
template <class _Tp>
24-
struct __libcpp_is_referenceable : integral_constant<bool, __is_referenceable(_Tp)> {};
25-
#else
26-
struct __libcpp_is_referenceable_impl {
27-
template <class _Tp>
28-
static _Tp& __test(int);
29-
template <class _Tp>
30-
static false_type __test(...);
31-
};
21+
template <class _Tp, class = void>
22+
inline const bool __is_referenceable_v = false;
3223

3324
template <class _Tp>
34-
struct __libcpp_is_referenceable
35-
: integral_constant<bool, _IsNotSame<decltype(__libcpp_is_referenceable_impl::__test<_Tp>(0)), false_type>::value> {
36-
};
37-
#endif // __has_builtin(__is_referenceable)
25+
inline const bool __is_referenceable_v<_Tp, __void_t<_Tp&> > = true;
3826

3927
_LIBCPP_END_NAMESPACE_STD
4028

Lines changed: 192 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,192 @@
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+
10+
// __is_referenceable_v<Tp>
11+
//
12+
// [defns.referenceable] defines "a referenceable type" as:
13+
// An object type, a function type that does not have cv-qualifiers
14+
// or a ref-qualifier, or a reference type.
15+
//
16+
17+
// XFAIL: FROZEN-CXX03-HEADERS-FIXME
18+
19+
#include <type_traits>
20+
#include <cassert>
21+
22+
#include "test_macros.h"
23+
24+
struct Foo {};
25+
26+
static_assert((!std::__is_referenceable_v<void>), "");
27+
static_assert((std::__is_referenceable_v<int>), "");
28+
static_assert((std::__is_referenceable_v<int[3]>), "");
29+
static_assert((std::__is_referenceable_v<int[]>), "");
30+
static_assert((std::__is_referenceable_v<int&>), "");
31+
static_assert((std::__is_referenceable_v<const int&>), "");
32+
static_assert((std::__is_referenceable_v<int*>), "");
33+
static_assert((std::__is_referenceable_v<const int*>), "");
34+
static_assert((std::__is_referenceable_v<Foo>), "");
35+
static_assert((std::__is_referenceable_v<const Foo>), "");
36+
static_assert((std::__is_referenceable_v<Foo&>), "");
37+
static_assert((std::__is_referenceable_v<const Foo&>), "");
38+
#if TEST_STD_VER >= 11
39+
static_assert((std::__is_referenceable_v<Foo&&>), "");
40+
static_assert((std::__is_referenceable_v<const Foo&&>), "");
41+
#endif
42+
43+
static_assert((std::__is_referenceable_v<int __attribute__((__vector_size__(8)))>), "");
44+
static_assert((std::__is_referenceable_v<const int __attribute__((__vector_size__(8)))>), "");
45+
static_assert((std::__is_referenceable_v<float __attribute__((__vector_size__(16)))>), "");
46+
static_assert((std::__is_referenceable_v<const float __attribute__((__vector_size__(16)))>), "");
47+
48+
// Functions without cv-qualifiers are referenceable
49+
static_assert((std::__is_referenceable_v<void()>), "");
50+
#if TEST_STD_VER >= 11
51+
static_assert((!std::__is_referenceable_v<void() const>), "");
52+
static_assert((!std::__is_referenceable_v<void() &>), "");
53+
static_assert((!std::__is_referenceable_v<void() const&>), "");
54+
static_assert((!std::__is_referenceable_v<void() &&>), "");
55+
static_assert((!std::__is_referenceable_v<void() const&&>), "");
56+
#endif
57+
58+
static_assert((std::__is_referenceable_v<void(int)>), "");
59+
#if TEST_STD_VER >= 11
60+
static_assert((!std::__is_referenceable_v<void(int) const>), "");
61+
static_assert((!std::__is_referenceable_v<void(int) &>), "");
62+
static_assert((!std::__is_referenceable_v<void(int) const&>), "");
63+
static_assert((!std::__is_referenceable_v<void(int) &&>), "");
64+
static_assert((!std::__is_referenceable_v<void(int) const&&>), "");
65+
#endif
66+
67+
static_assert((std::__is_referenceable_v<void(int, float)>), "");
68+
#if TEST_STD_VER >= 11
69+
static_assert((!std::__is_referenceable_v<void(int, float) const>), "");
70+
static_assert((!std::__is_referenceable_v<void(int, float) &>), "");
71+
static_assert((!std::__is_referenceable_v<void(int, float) const&>), "");
72+
static_assert((!std::__is_referenceable_v<void(int, float) &&>), "");
73+
static_assert((!std::__is_referenceable_v<void(int, float) const&&>), "");
74+
#endif
75+
76+
static_assert((std::__is_referenceable_v<void(int, float, Foo&)>), "");
77+
#if TEST_STD_VER >= 11
78+
static_assert((!std::__is_referenceable_v<void(int, float, Foo&) const>), "");
79+
static_assert((!std::__is_referenceable_v<void(int, float, Foo&) &>), "");
80+
static_assert((!std::__is_referenceable_v<void(int, float, Foo&) const&>), "");
81+
static_assert((!std::__is_referenceable_v<void(int, float, Foo&) &&>), "");
82+
static_assert((!std::__is_referenceable_v<void(int, float, Foo&) const&&>), "");
83+
#endif
84+
85+
static_assert((std::__is_referenceable_v<void(...)>), "");
86+
#if TEST_STD_VER >= 11
87+
static_assert((!std::__is_referenceable_v<void(...) const>), "");
88+
static_assert((!std::__is_referenceable_v<void(...) &>), "");
89+
static_assert((!std::__is_referenceable_v<void(...) const&>), "");
90+
static_assert((!std::__is_referenceable_v<void(...) &&>), "");
91+
static_assert((!std::__is_referenceable_v<void(...) const&&>), "");
92+
#endif
93+
94+
static_assert((std::__is_referenceable_v<void(int, ...)>), "");
95+
#if TEST_STD_VER >= 11
96+
static_assert((!std::__is_referenceable_v<void(int, ...) const>), "");
97+
static_assert((!std::__is_referenceable_v<void(int, ...) &>), "");
98+
static_assert((!std::__is_referenceable_v<void(int, ...) const&>), "");
99+
static_assert((!std::__is_referenceable_v<void(int, ...) &&>), "");
100+
static_assert((!std::__is_referenceable_v<void(int, ...) const&&>), "");
101+
#endif
102+
103+
static_assert((std::__is_referenceable_v<void(int, float, ...)>), "");
104+
#if TEST_STD_VER >= 11
105+
static_assert((!std::__is_referenceable_v<void(int, float, ...) const>), "");
106+
static_assert((!std::__is_referenceable_v<void(int, float, ...) &>), "");
107+
static_assert((!std::__is_referenceable_v<void(int, float, ...) const&>), "");
108+
static_assert((!std::__is_referenceable_v<void(int, float, ...) &&>), "");
109+
static_assert((!std::__is_referenceable_v<void(int, float, ...) const&&>), "");
110+
#endif
111+
112+
static_assert((std::__is_referenceable_v<void(int, float, Foo&, ...)>), "");
113+
#if TEST_STD_VER >= 11
114+
static_assert((!std::__is_referenceable_v<void(int, float, Foo&, ...) const>), "");
115+
static_assert((!std::__is_referenceable_v<void(int, float, Foo&, ...) &>), "");
116+
static_assert((!std::__is_referenceable_v<void(int, float, Foo&, ...) const&>), "");
117+
static_assert((!std::__is_referenceable_v<void(int, float, Foo&, ...) &&>), "");
118+
static_assert((!std::__is_referenceable_v<void(int, float, Foo&, ...) const&&>), "");
119+
#endif
120+
121+
// member functions with or without cv-qualifiers are referenceable
122+
static_assert((std::__is_referenceable_v<void (Foo::*)()>), "");
123+
static_assert((std::__is_referenceable_v<void (Foo::*)() const>), "");
124+
#if TEST_STD_VER >= 11
125+
static_assert((std::__is_referenceable_v<void (Foo::*)() &>), "");
126+
static_assert((std::__is_referenceable_v<void (Foo::*)() const&>), "");
127+
static_assert((std::__is_referenceable_v<void (Foo::*)() &&>), "");
128+
static_assert((std::__is_referenceable_v<void (Foo::*)() const&&>), "");
129+
#endif
130+
131+
static_assert((std::__is_referenceable_v<void (Foo::*)(int)>), "");
132+
static_assert((std::__is_referenceable_v<void (Foo::*)(int) const>), "");
133+
#if TEST_STD_VER >= 11
134+
static_assert((std::__is_referenceable_v<void (Foo::*)(int) &>), "");
135+
static_assert((std::__is_referenceable_v<void (Foo::*)(int) const&>), "");
136+
static_assert((std::__is_referenceable_v<void (Foo::*)(int) &&>), "");
137+
static_assert((std::__is_referenceable_v<void (Foo::*)(int) const&&>), "");
138+
#endif
139+
140+
static_assert((std::__is_referenceable_v<void (Foo::*)(int, float)>), "");
141+
static_assert((std::__is_referenceable_v<void (Foo::*)(int, float) const>), "");
142+
#if TEST_STD_VER >= 11
143+
static_assert((std::__is_referenceable_v<void (Foo::*)(int, float) &>), "");
144+
static_assert((std::__is_referenceable_v<void (Foo::*)(int, float) const&>), "");
145+
static_assert((std::__is_referenceable_v<void (Foo::*)(int, float) &&>), "");
146+
static_assert((std::__is_referenceable_v<void (Foo::*)(int, float) const&&>), "");
147+
#endif
148+
149+
static_assert((std::__is_referenceable_v<void (Foo::*)(int, float, Foo&)>), "");
150+
static_assert((std::__is_referenceable_v<void (Foo::*)(int, float, Foo&) const>), "");
151+
#if TEST_STD_VER >= 11
152+
static_assert((std::__is_referenceable_v<void (Foo::*)(int, float, Foo&) &>), "");
153+
static_assert((std::__is_referenceable_v<void (Foo::*)(int, float, Foo&) const&>), "");
154+
static_assert((std::__is_referenceable_v<void (Foo::*)(int, float, Foo&) &&>), "");
155+
static_assert((std::__is_referenceable_v<void (Foo::*)(int, float, Foo&) const&&>), "");
156+
#endif
157+
158+
static_assert((std::__is_referenceable_v<void (Foo::*)(...)>), "");
159+
static_assert((std::__is_referenceable_v<void (Foo::*)(...) const>), "");
160+
#if TEST_STD_VER >= 11
161+
static_assert((std::__is_referenceable_v<void (Foo::*)(...) &>), "");
162+
static_assert((std::__is_referenceable_v<void (Foo::*)(...) const&>), "");
163+
static_assert((std::__is_referenceable_v<void (Foo::*)(...) &&>), "");
164+
static_assert((std::__is_referenceable_v<void (Foo::*)(...) const&&>), "");
165+
#endif
166+
167+
static_assert((std::__is_referenceable_v<void (Foo::*)(int, ...)>), "");
168+
static_assert((std::__is_referenceable_v<void (Foo::*)(int, ...) const>), "");
169+
#if TEST_STD_VER >= 11
170+
static_assert((std::__is_referenceable_v<void (Foo::*)(int, ...) &>), "");
171+
static_assert((std::__is_referenceable_v<void (Foo::*)(int, ...) const&>), "");
172+
static_assert((std::__is_referenceable_v<void (Foo::*)(int, ...) &&>), "");
173+
static_assert((std::__is_referenceable_v<void (Foo::*)(int, ...) const&&>), "");
174+
#endif
175+
176+
static_assert((std::__is_referenceable_v<void (Foo::*)(int, float, ...)>), "");
177+
static_assert((std::__is_referenceable_v<void (Foo::*)(int, float, ...) const>), "");
178+
#if TEST_STD_VER >= 11
179+
static_assert((std::__is_referenceable_v<void (Foo::*)(int, float, ...) &>), "");
180+
static_assert((std::__is_referenceable_v<void (Foo::*)(int, float, ...) const&>), "");
181+
static_assert((std::__is_referenceable_v<void (Foo::*)(int, float, ...) &&>), "");
182+
static_assert((std::__is_referenceable_v<void (Foo::*)(int, float, ...) const&&>), "");
183+
#endif
184+
185+
static_assert((std::__is_referenceable_v<void (Foo::*)(int, float, Foo&, ...)>), "");
186+
static_assert((std::__is_referenceable_v<void (Foo::*)(int, float, Foo&, ...) const>), "");
187+
#if TEST_STD_VER >= 11
188+
static_assert((std::__is_referenceable_v<void (Foo::*)(int, float, Foo&, ...) &>), "");
189+
static_assert((std::__is_referenceable_v<void (Foo::*)(int, float, Foo&, ...) const&>), "");
190+
static_assert((std::__is_referenceable_v<void (Foo::*)(int, float, Foo&, ...) &&>), "");
191+
static_assert((std::__is_referenceable_v<void (Foo::*)(int, float, Foo&, ...) const&&>), "");
192+
#endif

0 commit comments

Comments
 (0)