template<typename _Tp>
auto declval() noexcept -> decltype(__declval<_Tp>(0));
- template<typename, unsigned = 0>
- struct extent;
-
template<typename>
struct remove_all_extents;
/// @cond undocumented
template<typename _Tp>
struct __is_array_known_bounds
- : public integral_constant<bool, (extent<_Tp>::value > 0)>
+ : public false_type
+ { };
+
+ template<typename _Tp, size_t _Size>
+ struct __is_array_known_bounds<_Tp[_Size]>
+ : public true_type
{ };
template<typename _Tp>
struct __is_array_unknown_bounds
- : public __and_<is_array<_Tp>, __not_<extent<_Tp>>>
+ : public false_type
+ { };
+
+ template<typename _Tp>
+ struct __is_array_unknown_bounds<_Tp[]>
+ : public true_type
{ };
// Destructible and constructible type properties.
: public integral_constant<std::size_t, 1 + rank<_Tp>::value> { };
/// extent
- template<typename, unsigned _Uint>
+ template<typename, unsigned _Uint = 0>
struct extent
- : public integral_constant<std::size_t, 0> { };
+ : public integral_constant<size_t, 0> { };
- template<typename _Tp, unsigned _Uint, std::size_t _Size>
+ template<typename _Tp, size_t _Size>
+ struct extent<_Tp[_Size], 0>
+ : public integral_constant<size_t, _Size> { };
+
+ template<typename _Tp, unsigned _Uint, size_t _Size>
struct extent<_Tp[_Size], _Uint>
- : public integral_constant<std::size_t,
- _Uint == 0 ? _Size : extent<_Tp,
- _Uint - 1>::value>
- { };
+ : public extent<_Tp, _Uint - 1>::type { };
+
+ template<typename _Tp>
+ struct extent<_Tp[], 0>
+ : public integral_constant<size_t, 0> { };
template<typename _Tp, unsigned _Uint>
struct extent<_Tp[], _Uint>
- : public integral_constant<std::size_t,
- _Uint == 0 ? 0 : extent<_Tp,
- _Uint - 1>::value>
- { };
+ : public extent<_Tp, _Uint - 1>::type { };
// Type relations.
inline constexpr bool is_integral_v = is_integral<_Tp>::value;
template <typename _Tp>
inline constexpr bool is_floating_point_v = is_floating_point<_Tp>::value;
+
+template <typename _Tp>
+ inline constexpr bool is_array_v = false;
template <typename _Tp>
- inline constexpr bool is_array_v = is_array<_Tp>::value;
+ inline constexpr bool is_array_v<_Tp[]> = true;
+template <typename _Tp, size_t _Num>
+ inline constexpr bool is_array_v<_Tp[_Num]> = true;
+
template <typename _Tp>
inline constexpr bool is_pointer_v = is_pointer<_Tp>::value;
template <typename _Tp>
has_virtual_destructor<_Tp>::value;
template <typename _Tp>
inline constexpr size_t alignment_of_v = alignment_of<_Tp>::value;
+
+template <typename _Tp>
+ inline constexpr size_t rank_v = 0;
+template <typename _Tp, size_t _Size>
+ inline constexpr size_t rank_v<_Tp[_Size]> = 1 + rank_v<_Tp>;
template <typename _Tp>
- inline constexpr size_t rank_v = rank<_Tp>::value;
+ inline constexpr size_t rank_v<_Tp[]> = 1 + rank_v<_Tp>;
+
template <typename _Tp, unsigned _Idx = 0>
- inline constexpr size_t extent_v = extent<_Tp, _Idx>::value;
+ inline constexpr size_t extent_v = 0;
+template <typename _Tp, size_t _Size>
+ inline constexpr size_t extent_v<_Tp[_Size], 0> = _Size;
+template <typename _Tp, unsigned _Idx, size_t _Size>
+ inline constexpr size_t extent_v<_Tp[_Size], _Idx> = extent_v<_Tp, _Idx - 1>;
+template <typename _Tp>
+ inline constexpr size_t extent_v<_Tp[], 0> = 0;
+template <typename _Tp, unsigned _Idx>
+ inline constexpr size_t extent_v<_Tp[], _Idx> = extent_v<_Tp, _Idx - 1>;
+
#ifdef _GLIBCXX_HAVE_BUILTIN_IS_SAME
template <typename _Tp, typename _Up>
inline constexpr bool is_same_v = __is_same(_Tp, _Up);
#define __cpp_lib_bounded_array_traits 201902L
/// True for a type that is an array of known bound.
+ /// @ingroup variable_templates
/// @since C++20
template<typename _Tp>
- struct is_bounded_array
- : public __is_array_known_bounds<_Tp>
- { };
+ inline constexpr bool is_bounded_array_v = false;
+
+ template<typename _Tp, size_t _Size>
+ inline constexpr bool is_bounded_array_v<_Tp[_Size]> = true;
/// True for a type that is an array of unknown bound.
+ /// @ingroup variable_templates
/// @since C++20
template<typename _Tp>
- struct is_unbounded_array
- : public __is_array_unknown_bounds<_Tp>
- { };
+ inline constexpr bool is_unbounded_array_v = false;
- /// @ingroup variable_templates
+ template<typename _Tp>
+ inline constexpr bool is_unbounded_array_v<_Tp[]> = true;
+
+ /// True for a type that is an array of known bound.
/// @since C++20
template<typename _Tp>
- inline constexpr bool is_bounded_array_v
- = is_bounded_array<_Tp>::value;
+ struct is_bounded_array
+ : public bool_constant<is_bounded_array_v<_Tp>>
+ { };
- /// @ingroup variable_templates
+ /// True for a type that is an array of unknown bound.
/// @since C++20
template<typename _Tp>
- inline constexpr bool is_unbounded_array_v
- = is_unbounded_array<_Tp>::value;
+ struct is_unbounded_array
+ : public bool_constant<is_unbounded_array_v<_Tp>>
+ { };
#if __has_builtin(__is_layout_compatible)