-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[libc++] Simplify the implementation of __is_referenceable #130043
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
8970df3
to
fa87f65
Compare
@llvm/pr-subscribers-libcxx Author: Nikolas Klauser (philnik777) ChangesThe Patch is 26.70 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/130043.diff 8 Files Affected:
diff --git a/libcxx/include/__type_traits/add_lvalue_reference.h b/libcxx/include/__type_traits/add_lvalue_reference.h
index f861420a10e05..5e65477058e5f 100644
--- a/libcxx/include/__type_traits/add_lvalue_reference.h
+++ b/libcxx/include/__type_traits/add_lvalue_reference.h
@@ -25,7 +25,7 @@ using __add_lvalue_reference_t _LIBCPP_NODEBUG = __add_lvalue_reference(_Tp);
#else
-template <class _Tp, bool = __libcpp_is_referenceable<_Tp>::value>
+template <class _Tp, bool = __is_referenceable_v<_Tp>>
struct __add_lvalue_reference_impl {
using type _LIBCPP_NODEBUG = _Tp;
};
diff --git a/libcxx/include/__type_traits/add_pointer.h b/libcxx/include/__type_traits/add_pointer.h
index d10b5cf70c64d..a9a51b86abaf0 100644
--- a/libcxx/include/__type_traits/add_pointer.h
+++ b/libcxx/include/__type_traits/add_pointer.h
@@ -26,7 +26,7 @@ template <class _Tp>
using __add_pointer_t _LIBCPP_NODEBUG = __add_pointer(_Tp);
#else
-template <class _Tp, bool = __libcpp_is_referenceable<_Tp>::value || is_void<_Tp>::value>
+template <class _Tp, bool = __is_referenceable_v<_Tp> || is_void<_Tp>::value>
struct __add_pointer_impl {
using type _LIBCPP_NODEBUG = __libcpp_remove_reference_t<_Tp>*;
};
diff --git a/libcxx/include/__type_traits/add_rvalue_reference.h b/libcxx/include/__type_traits/add_rvalue_reference.h
index ed4f8633bce1f..2d60fc9f2c20a 100644
--- a/libcxx/include/__type_traits/add_rvalue_reference.h
+++ b/libcxx/include/__type_traits/add_rvalue_reference.h
@@ -25,7 +25,7 @@ using __add_rvalue_reference_t _LIBCPP_NODEBUG = __add_rvalue_reference(_Tp);
#else
-template <class _Tp, bool = __libcpp_is_referenceable<_Tp>::value>
+template <class _Tp, bool = __is_referenceable_v<_Tp> >
struct __add_rvalue_reference_impl {
using type _LIBCPP_NODEBUG = _Tp;
};
diff --git a/libcxx/include/__type_traits/decay.h b/libcxx/include/__type_traits/decay.h
index 2fd73d3dde45d..4bf0b4c1fedb7 100644
--- a/libcxx/include/__type_traits/decay.h
+++ b/libcxx/include/__type_traits/decay.h
@@ -55,7 +55,7 @@ struct _LIBCPP_TEMPLATE_VIS decay {
using _Up _LIBCPP_NODEBUG = __libcpp_remove_reference_t<_Tp>;
public:
- using type _LIBCPP_NODEBUG = typename __decay<_Up, __libcpp_is_referenceable<_Up>::value>::type;
+ using type _LIBCPP_NODEBUG = typename __decay<_Up, __is_referenceable_v<_Up> >::type;
};
template <class _Tp>
diff --git a/libcxx/include/__type_traits/is_referenceable.h b/libcxx/include/__type_traits/is_referenceable.h
index 4b34ec2572317..994c36b63d07f 100644
--- a/libcxx/include/__type_traits/is_referenceable.h
+++ b/libcxx/include/__type_traits/is_referenceable.h
@@ -10,8 +10,7 @@
#define _LIBCPP___TYPE_TRAITS_IS_REFERENCEABLE_H
#include <__config>
-#include <__type_traits/integral_constant.h>
-#include <__type_traits/is_same.h>
+#include <__type_traits/void_t.h>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
@@ -19,22 +18,11 @@
_LIBCPP_BEGIN_NAMESPACE_STD
-#if __has_builtin(__is_referenceable)
-template <class _Tp>
-struct __libcpp_is_referenceable : integral_constant<bool, __is_referenceable(_Tp)> {};
-#else
-struct __libcpp_is_referenceable_impl {
- template <class _Tp>
- static _Tp& __test(int);
- template <class _Tp>
- static false_type __test(...);
-};
+template <class _Tp, class = void>
+inline const bool __is_referenceable_v = false;
template <class _Tp>
-struct __libcpp_is_referenceable
- : integral_constant<bool, _IsNotSame<decltype(__libcpp_is_referenceable_impl::__test<_Tp>(0)), false_type>::value> {
-};
-#endif // __has_builtin(__is_referenceable)
+inline const bool __is_referenceable_v<_Tp, __void_t<_Tp&> > = true;
_LIBCPP_END_NAMESPACE_STD
diff --git a/libcxx/test/libcxx/utilities/meta/is_referenceable.compile.pass.cpp b/libcxx/test/libcxx/utilities/meta/is_referenceable.compile.pass.cpp
new file mode 100644
index 0000000000000..0991de69b5baf
--- /dev/null
+++ b/libcxx/test/libcxx/utilities/meta/is_referenceable.compile.pass.cpp
@@ -0,0 +1,192 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+//
+
+// __is_referenceable_v<Tp>
+//
+// [defns.referenceable] defines "a referenceable type" as:
+// An object type, a function type that does not have cv-qualifiers
+// or a ref-qualifier, or a reference type.
+//
+
+// XFAIL: FROZEN-CXX03-HEADERS-FIXME
+
+#include <type_traits>
+#include <cassert>
+
+#include "test_macros.h"
+
+struct Foo {};
+
+static_assert((!std::__is_referenceable_v<void>), "");
+static_assert((std::__is_referenceable_v<int>), "");
+static_assert((std::__is_referenceable_v<int[3]>), "");
+static_assert((std::__is_referenceable_v<int[]>), "");
+static_assert((std::__is_referenceable_v<int&>), "");
+static_assert((std::__is_referenceable_v<const int&>), "");
+static_assert((std::__is_referenceable_v<int*>), "");
+static_assert((std::__is_referenceable_v<const int*>), "");
+static_assert((std::__is_referenceable_v<Foo>), "");
+static_assert((std::__is_referenceable_v<const Foo>), "");
+static_assert((std::__is_referenceable_v<Foo&>), "");
+static_assert((std::__is_referenceable_v<const Foo&>), "");
+#if TEST_STD_VER >= 11
+static_assert((std::__is_referenceable_v<Foo&&>), "");
+static_assert((std::__is_referenceable_v<const Foo&&>), "");
+#endif
+
+static_assert((std::__is_referenceable_v<int __attribute__((__vector_size__(8)))>), "");
+static_assert((std::__is_referenceable_v<const int __attribute__((__vector_size__(8)))>), "");
+static_assert((std::__is_referenceable_v<float __attribute__((__vector_size__(16)))>), "");
+static_assert((std::__is_referenceable_v<const float __attribute__((__vector_size__(16)))>), "");
+
+// Functions without cv-qualifiers are referenceable
+static_assert((std::__is_referenceable_v<void()>), "");
+#if TEST_STD_VER >= 11
+static_assert((!std::__is_referenceable_v<void() const>), "");
+static_assert((!std::__is_referenceable_v<void() &>), "");
+static_assert((!std::__is_referenceable_v<void() const&>), "");
+static_assert((!std::__is_referenceable_v<void() &&>), "");
+static_assert((!std::__is_referenceable_v<void() const&&>), "");
+#endif
+
+static_assert((std::__is_referenceable_v<void(int)>), "");
+#if TEST_STD_VER >= 11
+static_assert((!std::__is_referenceable_v<void(int) const>), "");
+static_assert((!std::__is_referenceable_v<void(int) &>), "");
+static_assert((!std::__is_referenceable_v<void(int) const&>), "");
+static_assert((!std::__is_referenceable_v<void(int) &&>), "");
+static_assert((!std::__is_referenceable_v<void(int) const&&>), "");
+#endif
+
+static_assert((std::__is_referenceable_v<void(int, float)>), "");
+#if TEST_STD_VER >= 11
+static_assert((!std::__is_referenceable_v<void(int, float) const>), "");
+static_assert((!std::__is_referenceable_v<void(int, float) &>), "");
+static_assert((!std::__is_referenceable_v<void(int, float) const&>), "");
+static_assert((!std::__is_referenceable_v<void(int, float) &&>), "");
+static_assert((!std::__is_referenceable_v<void(int, float) const&&>), "");
+#endif
+
+static_assert((std::__is_referenceable_v<void(int, float, Foo&)>), "");
+#if TEST_STD_VER >= 11
+static_assert((!std::__is_referenceable_v<void(int, float, Foo&) const>), "");
+static_assert((!std::__is_referenceable_v<void(int, float, Foo&) &>), "");
+static_assert((!std::__is_referenceable_v<void(int, float, Foo&) const&>), "");
+static_assert((!std::__is_referenceable_v<void(int, float, Foo&) &&>), "");
+static_assert((!std::__is_referenceable_v<void(int, float, Foo&) const&&>), "");
+#endif
+
+static_assert((std::__is_referenceable_v<void(...)>), "");
+#if TEST_STD_VER >= 11
+static_assert((!std::__is_referenceable_v<void(...) const>), "");
+static_assert((!std::__is_referenceable_v<void(...) &>), "");
+static_assert((!std::__is_referenceable_v<void(...) const&>), "");
+static_assert((!std::__is_referenceable_v<void(...) &&>), "");
+static_assert((!std::__is_referenceable_v<void(...) const&&>), "");
+#endif
+
+static_assert((std::__is_referenceable_v<void(int, ...)>), "");
+#if TEST_STD_VER >= 11
+static_assert((!std::__is_referenceable_v<void(int, ...) const>), "");
+static_assert((!std::__is_referenceable_v<void(int, ...) &>), "");
+static_assert((!std::__is_referenceable_v<void(int, ...) const&>), "");
+static_assert((!std::__is_referenceable_v<void(int, ...) &&>), "");
+static_assert((!std::__is_referenceable_v<void(int, ...) const&&>), "");
+#endif
+
+static_assert((std::__is_referenceable_v<void(int, float, ...)>), "");
+#if TEST_STD_VER >= 11
+static_assert((!std::__is_referenceable_v<void(int, float, ...) const>), "");
+static_assert((!std::__is_referenceable_v<void(int, float, ...) &>), "");
+static_assert((!std::__is_referenceable_v<void(int, float, ...) const&>), "");
+static_assert((!std::__is_referenceable_v<void(int, float, ...) &&>), "");
+static_assert((!std::__is_referenceable_v<void(int, float, ...) const&&>), "");
+#endif
+
+static_assert((std::__is_referenceable_v<void(int, float, Foo&, ...)>), "");
+#if TEST_STD_VER >= 11
+static_assert((!std::__is_referenceable_v<void(int, float, Foo&, ...) const>), "");
+static_assert((!std::__is_referenceable_v<void(int, float, Foo&, ...) &>), "");
+static_assert((!std::__is_referenceable_v<void(int, float, Foo&, ...) const&>), "");
+static_assert((!std::__is_referenceable_v<void(int, float, Foo&, ...) &&>), "");
+static_assert((!std::__is_referenceable_v<void(int, float, Foo&, ...) const&&>), "");
+#endif
+
+// member functions with or without cv-qualifiers are referenceable
+static_assert((std::__is_referenceable_v<void (Foo::*)()>), "");
+static_assert((std::__is_referenceable_v<void (Foo::*)() const>), "");
+#if TEST_STD_VER >= 11
+static_assert((std::__is_referenceable_v<void (Foo::*)() &>), "");
+static_assert((std::__is_referenceable_v<void (Foo::*)() const&>), "");
+static_assert((std::__is_referenceable_v<void (Foo::*)() &&>), "");
+static_assert((std::__is_referenceable_v<void (Foo::*)() const&&>), "");
+#endif
+
+static_assert((std::__is_referenceable_v<void (Foo::*)(int)>), "");
+static_assert((std::__is_referenceable_v<void (Foo::*)(int) const>), "");
+#if TEST_STD_VER >= 11
+static_assert((std::__is_referenceable_v<void (Foo::*)(int) &>), "");
+static_assert((std::__is_referenceable_v<void (Foo::*)(int) const&>), "");
+static_assert((std::__is_referenceable_v<void (Foo::*)(int) &&>), "");
+static_assert((std::__is_referenceable_v<void (Foo::*)(int) const&&>), "");
+#endif
+
+static_assert((std::__is_referenceable_v<void (Foo::*)(int, float)>), "");
+static_assert((std::__is_referenceable_v<void (Foo::*)(int, float) const>), "");
+#if TEST_STD_VER >= 11
+static_assert((std::__is_referenceable_v<void (Foo::*)(int, float) &>), "");
+static_assert((std::__is_referenceable_v<void (Foo::*)(int, float) const&>), "");
+static_assert((std::__is_referenceable_v<void (Foo::*)(int, float) &&>), "");
+static_assert((std::__is_referenceable_v<void (Foo::*)(int, float) const&&>), "");
+#endif
+
+static_assert((std::__is_referenceable_v<void (Foo::*)(int, float, Foo&)>), "");
+static_assert((std::__is_referenceable_v<void (Foo::*)(int, float, Foo&) const>), "");
+#if TEST_STD_VER >= 11
+static_assert((std::__is_referenceable_v<void (Foo::*)(int, float, Foo&) &>), "");
+static_assert((std::__is_referenceable_v<void (Foo::*)(int, float, Foo&) const&>), "");
+static_assert((std::__is_referenceable_v<void (Foo::*)(int, float, Foo&) &&>), "");
+static_assert((std::__is_referenceable_v<void (Foo::*)(int, float, Foo&) const&&>), "");
+#endif
+
+static_assert((std::__is_referenceable_v<void (Foo::*)(...)>), "");
+static_assert((std::__is_referenceable_v<void (Foo::*)(...) const>), "");
+#if TEST_STD_VER >= 11
+static_assert((std::__is_referenceable_v<void (Foo::*)(...) &>), "");
+static_assert((std::__is_referenceable_v<void (Foo::*)(...) const&>), "");
+static_assert((std::__is_referenceable_v<void (Foo::*)(...) &&>), "");
+static_assert((std::__is_referenceable_v<void (Foo::*)(...) const&&>), "");
+#endif
+
+static_assert((std::__is_referenceable_v<void (Foo::*)(int, ...)>), "");
+static_assert((std::__is_referenceable_v<void (Foo::*)(int, ...) const>), "");
+#if TEST_STD_VER >= 11
+static_assert((std::__is_referenceable_v<void (Foo::*)(int, ...) &>), "");
+static_assert((std::__is_referenceable_v<void (Foo::*)(int, ...) const&>), "");
+static_assert((std::__is_referenceable_v<void (Foo::*)(int, ...) &&>), "");
+static_assert((std::__is_referenceable_v<void (Foo::*)(int, ...) const&&>), "");
+#endif
+
+static_assert((std::__is_referenceable_v<void (Foo::*)(int, float, ...)>), "");
+static_assert((std::__is_referenceable_v<void (Foo::*)(int, float, ...) const>), "");
+#if TEST_STD_VER >= 11
+static_assert((std::__is_referenceable_v<void (Foo::*)(int, float, ...) &>), "");
+static_assert((std::__is_referenceable_v<void (Foo::*)(int, float, ...) const&>), "");
+static_assert((std::__is_referenceable_v<void (Foo::*)(int, float, ...) &&>), "");
+static_assert((std::__is_referenceable_v<void (Foo::*)(int, float, ...) const&&>), "");
+#endif
+
+static_assert((std::__is_referenceable_v<void (Foo::*)(int, float, Foo&, ...)>), "");
+static_assert((std::__is_referenceable_v<void (Foo::*)(int, float, Foo&, ...) const>), "");
+#if TEST_STD_VER >= 11
+static_assert((std::__is_referenceable_v<void (Foo::*)(int, float, Foo&, ...) &>), "");
+static_assert((std::__is_referenceable_v<void (Foo::*)(int, float, Foo&, ...) const&>), "");
+static_assert((std::__is_referenceable_v<void (Foo::*)(int, float, Foo&, ...) &&>), "");
+static_assert((std::__is_referenceable_v<void (Foo::*)(int, float, Foo&, ...) const&&>), "");
+#endif
diff --git a/libcxx/test/libcxx/utilities/meta/is_referenceable.pass.cpp b/libcxx/test/libcxx/utilities/meta/is_referenceable.pass.cpp
deleted file mode 100644
index 336f6e82ce8de..0000000000000
--- a/libcxx/test/libcxx/utilities/meta/is_referenceable.pass.cpp
+++ /dev/null
@@ -1,194 +0,0 @@
-//===----------------------------------------------------------------------===//
-//
-// 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
-//
-//===----------------------------------------------------------------------===//
-//
-
-// __libcpp_is_referenceable<Tp>
-//
-// [defns.referenceable] defines "a referenceable type" as:
-// An object type, a function type that does not have cv-qualifiers
-// or a ref-qualifier, or a reference type.
-//
-
-#include <type_traits>
-#include <cassert>
-
-#include "test_macros.h"
-
-struct Foo {};
-
-static_assert((!std::__libcpp_is_referenceable<void>::value), "");
-static_assert((std::__libcpp_is_referenceable<int>::value), "");
-static_assert((std::__libcpp_is_referenceable<int[3]>::value), "");
-static_assert((std::__libcpp_is_referenceable<int[]>::value), "");
-static_assert((std::__libcpp_is_referenceable<int&>::value), "");
-static_assert((std::__libcpp_is_referenceable<const int&>::value), "");
-static_assert((std::__libcpp_is_referenceable<int*>::value), "");
-static_assert((std::__libcpp_is_referenceable<const int*>::value), "");
-static_assert((std::__libcpp_is_referenceable<Foo>::value), "");
-static_assert((std::__libcpp_is_referenceable<const Foo>::value), "");
-static_assert((std::__libcpp_is_referenceable<Foo&>::value), "");
-static_assert((std::__libcpp_is_referenceable<const Foo&>::value), "");
-#if TEST_STD_VER >= 11
-static_assert((std::__libcpp_is_referenceable<Foo&&>::value), "");
-static_assert((std::__libcpp_is_referenceable<const Foo&&>::value), "");
-#endif
-
-static_assert((std::__libcpp_is_referenceable<int __attribute__((__vector_size__(8)))>::value), "");
-static_assert((std::__libcpp_is_referenceable<const int __attribute__((__vector_size__(8)))>::value), "");
-static_assert((std::__libcpp_is_referenceable<float __attribute__((__vector_size__(16)))>::value), "");
-static_assert((std::__libcpp_is_referenceable<const float __attribute__((__vector_size__(16)))>::value), "");
-
-// Functions without cv-qualifiers are referenceable
-static_assert((std::__libcpp_is_referenceable<void()>::value), "");
-#if TEST_STD_VER >= 11
-static_assert((!std::__libcpp_is_referenceable<void() const>::value), "");
-static_assert((!std::__libcpp_is_referenceable<void() &>::value), "");
-static_assert((!std::__libcpp_is_referenceable<void() const&>::value), "");
-static_assert((!std::__libcpp_is_referenceable<void() &&>::value), "");
-static_assert((!std::__libcpp_is_referenceable<void() const&&>::value), "");
-#endif
-
-static_assert((std::__libcpp_is_referenceable<void(int)>::value), "");
-#if TEST_STD_VER >= 11
-static_assert((!std::__libcpp_is_referenceable<void(int) const>::value), "");
-static_assert((!std::__libcpp_is_referenceable<void(int) &>::value), "");
-static_assert((!std::__libcpp_is_referenceable<void(int) const&>::value), "");
-static_assert((!std::__libcpp_is_referenceable<void(int) &&>::value), "");
-static_assert((!std::__libcpp_is_referenceable<void(int) const&&>::value), "");
-#endif
-
-static_assert((std::__libcpp_is_referenceable<void(int, float)>::value), "");
-#if TEST_STD_VER >= 11
-static_assert((!std::__libcpp_is_referenceable<void(int, float) const>::value), "");
-static_assert((!std::__libcpp_is_referenceable<void(int, float) &>::value), "");
-static_assert((!std::__libcpp_is_referenceable<void(int, float) const&>::value), "");
-static_assert((!std::__libcpp_is_referenceable<void(int, float) &&>::value), "");
-static_assert((!std::__libcpp_is_referenceable<void(int, float) const&&>::value), "");
-#endif
-
-static_assert((std::__libcpp_is_referenceable<void(int, float, Foo&)>::value), "");
-#if TEST_STD_VER >= 11
-static_assert((!std::__libcpp_is_referenceable<void(int, float, Foo&) const>::value), "");
-static_assert((!std::__libcpp_is_referenceable<void(int, float, Foo&) &>::value), "");
-static_assert((!std::__libcpp_is_referenceable<void(int, float, Foo&) const&>::value), "");
-static_assert((!std::__libcpp_is_referenceable<void(int, float, Foo&) &&>::value), "");
-static_assert((!std::__libcpp_is_referenceable<void(int, float, Foo&) const&&>::value), "");
-#endif
-
-static_assert((std::__libcpp_is_referenceable<void(...)>::value), "");
-#if TEST_STD_VER >= 11
-static_assert((!std::__libcpp_is_referenceable<void(...) const>::value), "");
-static_assert((!std::__libcpp_is_referenceable<void(...) &>::value), "");
-static_assert((!std::__libcpp_is_referenceable<void(...) const&>::value), "");
-static_assert((!std::__libcpp_is_referenceable<void(...) &&>::value), "");
-static_assert((!std::__libcpp_is_referenceable<void(...) const&&>::value), "");
-#endif
-
-static_assert((std::__libcpp_is_referenceable<void(int, ...)>::value), "");
-#if TEST_STD_VER >= 11
-static_assert((!std::__libcpp_is_referenceable<void(int, ...) const>::value), "");
-static_assert((!std::__libcpp_is_referenceable<void(int, ...) &>::value), "");
-static_assert((!std::__libcpp_is_referenceable<void(int, ...) const&>::value), "");
-static_assert((!std::__libcpp_is_referenceable<void(int, ...) &&>::value), "");
-static_assert((!std::__libcpp_is_referenceable<void(int, ...) const&&>::value), "");
-#endif
-
-static_assert((std::__libcpp_is_referenceable<void(int, float, ...)>::value), "");
-#if TEST_STD_VER >= 11
-static_assert((!std::__libcpp_is_referenceable<void(int, float, ...) const>::value), "");
-static_assert((!std::__libcpp_is_referenceable<void(int, float, ...) &>::value), "");
-static_assert((!std::__libcpp_is_referenceable<void(int, float, ...) const&>::value), "");
-static_assert((!std::__libcpp_is_referenceable<void(int, float, ...) &&>::value), "");
-static_assert((!std::__libcpp_is_referenceable<void(int, float, ...) const&&>::value), "");
-#endif
-
-static_assert((std::__libcpp_is_referenceable<void(int, float, Foo&, ...)>::value), "");
-#if TEST_STD_VER >= 11
-static_assert((!std::__libcpp_is_referenceable<void(int, float, Foo&, ...) const>::value), "");
-static_assert((!std::__libcpp_is_referenceable<void(int, float, Foo&, ...) &>::value), "");
-static_assert((!std::__libcpp_is_referenceable<void(int, float, Foo&, ...) const&>::value), "");
-static_assert((!std::__libcpp_...
[truncated]
|
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.