template <class T> struct remove_extent;
template <class T> struct remove_all_extents;
+ template <class T> struct is_bounded_array; // C++20
+ template <class T> struct is_unbounded_array; // C++20
+
// Member introspection:
template <class T> struct is_pod;
template <class T> struct is_trivial;
template <class T>
using remove_all_extents_t = typename remove_all_extents<T>::type; // C++14
+ template <class T>
+ inline constexpr bool is_bounded_array_v
+ = is_bounded_array<T>::value; // C++20
+ inline constexpr bool is_unbounded_array_v
+ = is_unbounded_array<T>::value; // C++20
+
// pointer modifications:
template <class T>
using remove_pointer_t = typename remove_pointer<T>::type; // C++14
template <class _Tp> using remove_all_extents_t = typename remove_all_extents<_Tp>::type;
#endif
+#if _LIBCPP_STD_VER > 17
+// is_bounded_array
+
+template <class> struct _LIBCPP_TEMPLATE_VIS is_bounded_array : false_type {};
+template <class _Tp, size_t _Np> struct _LIBCPP_TEMPLATE_VIS is_bounded_array<_Tp[_Np]> : true_type {};
+
+template <class _Tp>
+_LIBCPP_INLINE_VAR _LIBCPP_CONSTEXPR
+bool is_bounded_array_v = is_bounded_array<_Tp>::value;
+
+// is_unbounded_array
+
+template <class> struct _LIBCPP_TEMPLATE_VIS is_unbounded_array : false_type {};
+template <class _Tp> struct _LIBCPP_TEMPLATE_VIS is_unbounded_array<_Tp[]> : true_type {};
+
+template <class _Tp>
+_LIBCPP_INLINE_VAR _LIBCPP_CONSTEXPR
+bool is_unbounded_array_v = is_unbounded_array<_Tp>::value;
+#endif
+
// decay
template <class _Up, bool>
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// 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++98, c++03, c++11, c++14, c++17
+
+// type_traits
+
+// is_bounded_array<T>
+// T is an array type of known bound ([dcl.array])
+
+#include <type_traits>
+
+template <class T, bool B>
+void test_array_imp()
+{
+ static_assert( B == std::is_bounded_array<T>::value, "" );
+ static_assert( B == std::is_bounded_array_v<T>, "" );
+}
+
+template <class T, bool B>
+void test_array()
+{
+ test_array_imp<T, B>();
+ test_array_imp<const T, B>();
+ test_array_imp<volatile T, B>();
+ test_array_imp<const volatile T, B>();
+}
+
+typedef char array[3];
+typedef char incomplete_array[];
+
+class incomplete_type;
+
+class Empty {};
+union Union {};
+
+class Abstract
+{
+ virtual ~Abstract() = 0;
+};
+
+enum Enum {zero, one};
+typedef void (*FunctionPtr)();
+
+int main(int, char**)
+{
+// Non-array types
+ test_array<void, false>();
+ test_array<std::nullptr_t, false>();
+ test_array<int, false>();
+ test_array<double, false>();
+ test_array<void *, false>();
+ test_array<int &, false>();
+ test_array<int &&, false>();
+ test_array<Empty, false>();
+ test_array<Union, false>();
+ test_array<Abstract, false>();
+ test_array<Enum, false>();
+ test_array<FunctionPtr, false>();
+
+// Array types
+ test_array<array, true>();
+ test_array<incomplete_array, false>();
+ test_array<incomplete_type[], false>();
+
+ return 0;
+}
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// 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++98, c++03, c++11, c++14, c++17
+
+// type_traits
+
+// is_unbounded_array<T>
+// T is an array type of unknown bound ([dcl.array])
+
+#include <type_traits>
+
+template <class T, bool B>
+void test_array_imp()
+{
+ static_assert( B == std::is_unbounded_array<T>::value, "" );
+ static_assert( B == std::is_unbounded_array_v<T>, "" );
+}
+
+template <class T, bool B>
+void test_array()
+{
+ test_array_imp<T, B>();
+ test_array_imp<const T, B>();
+ test_array_imp<volatile T, B>();
+ test_array_imp<const volatile T, B>();
+}
+
+typedef char array[3];
+typedef char incomplete_array[];
+
+class incomplete_type;
+
+class Empty {};
+union Union {};
+
+class Abstract
+{
+ virtual ~Abstract() = 0;
+};
+
+enum Enum {zero, one};
+typedef void (*FunctionPtr)();
+
+int main(int, char**)
+{
+// Non-array types
+ test_array<void, false>();
+ test_array<std::nullptr_t, false>();
+ test_array<int, false>();
+ test_array<double, false>();
+ test_array<void *, false>();
+ test_array<int &, false>();
+ test_array<int &&, false>();
+ test_array<Empty, false>();
+ test_array<Union, false>();
+ test_array<Abstract, false>();
+ test_array<Enum, false>();
+ test_array<FunctionPtr, false>();
+
+// Array types
+ test_array<array, false>();
+ test_array<incomplete_array, true>();
+ test_array<incomplete_type[], true>();
+
+ return 0;
+}