Skip to content

Commit e5d5146

Browse files
committed
[libc] Allow construction of const span from mutable span
1 parent 1d66c5e commit e5d5146

File tree

3 files changed

+33
-37
lines changed

3 files changed

+33
-37
lines changed

libc/src/__support/CPP/span.h

+7-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
#include <stddef.h> // For size_t
1212

1313
#include "array.h" // For array
14-
#include "type_traits.h" // For remove_cv_t
14+
#include "type_traits.h" // For remove_cv_t, enable_if_t, is_same_v, is_const_v
1515

1616
namespace __llvm_libc::cpp {
1717

@@ -52,6 +52,12 @@ template <typename T> class span {
5252
constexpr span(array<T, N> &arr)
5353
: span_data(arr.data()), span_size(arr.size()) {}
5454

55+
template <typename U,
56+
cpp::enable_if_t<!cpp::is_const_v<U> && cpp::is_const_v<T> &&
57+
cpp::is_same_v<U, value_type>,
58+
bool> = true>
59+
constexpr span(span<U> &s) : span(s.data(), s.size()) {}
60+
5561
constexpr span(const span &s) = default;
5662
constexpr span &operator=(const span &s) = default;
5763
~span() = default;

libc/src/__support/CPP/type_traits.h

+16-36
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,7 @@ namespace __llvm_libc {
1515
namespace cpp {
1616

1717
template <bool B, typename T> struct enable_if;
18-
template <typename T> struct enable_if<true, T> {
19-
using type = T;
20-
};
18+
template <typename T> struct enable_if<true, T> { using type = T; };
2119
template <bool B, typename T = void>
2220
using enable_if_t = typename enable_if<B, T>::type;
2321

@@ -28,15 +26,17 @@ template <typename T, T v> struct integral_constant {
2826
using true_type = cpp::integral_constant<bool, true>;
2927
using false_type = cpp::integral_constant<bool, false>;
3028

31-
template <typename T> struct type_identity {
32-
using type = T;
33-
};
29+
template <typename T> struct type_identity { using type = T; };
3430

3531
template <typename T, typename U> struct is_same : cpp::false_type {};
3632
template <typename T> struct is_same<T, T> : cpp::true_type {};
3733
template <typename T, typename U>
3834
inline constexpr bool is_same_v = is_same<T, U>::value;
3935

36+
template <class T> struct is_const : cpp::false_type {};
37+
template <class T> struct is_const<const T> : cpp::true_type {};
38+
template <class T> inline constexpr bool is_const_v = is_const<T>::value;
39+
4040
template <typename T> struct remove_cv : public type_identity<T> {};
4141
template <typename T> struct remove_cv<const T> : public type_identity<T> {};
4242
template <typename T> struct remove_cv<volatile T> : public type_identity<T> {};
@@ -114,46 +114,26 @@ template <typename T> struct is_signed {
114114
template <typename T> inline constexpr bool is_signed_v = is_signed<T>::value;
115115

116116
template <typename T> struct make_unsigned;
117-
template <> struct make_unsigned<char> {
118-
using type = unsigned char;
119-
};
120-
template <> struct make_unsigned<signed char> {
121-
using type = unsigned char;
122-
};
123-
template <> struct make_unsigned<short> {
124-
using type = unsigned short;
125-
};
126-
template <> struct make_unsigned<int> {
127-
using type = unsigned int;
128-
};
129-
template <> struct make_unsigned<long> {
130-
using type = unsigned long;
131-
};
117+
template <> struct make_unsigned<char> { using type = unsigned char; };
118+
template <> struct make_unsigned<signed char> { using type = unsigned char; };
119+
template <> struct make_unsigned<short> { using type = unsigned short; };
120+
template <> struct make_unsigned<int> { using type = unsigned int; };
121+
template <> struct make_unsigned<long> { using type = unsigned long; };
132122
template <> struct make_unsigned<long long> {
133123
using type = unsigned long long;
134124
};
135-
template <> struct make_unsigned<unsigned char> {
136-
using type = unsigned char;
137-
};
125+
template <> struct make_unsigned<unsigned char> { using type = unsigned char; };
138126
template <> struct make_unsigned<unsigned short> {
139127
using type = unsigned short;
140128
};
141-
template <> struct make_unsigned<unsigned int> {
142-
using type = unsigned int;
143-
};
144-
template <> struct make_unsigned<unsigned long> {
145-
using type = unsigned long;
146-
};
129+
template <> struct make_unsigned<unsigned int> { using type = unsigned int; };
130+
template <> struct make_unsigned<unsigned long> { using type = unsigned long; };
147131
template <> struct make_unsigned<unsigned long long> {
148132
using type = unsigned long long;
149133
};
150134
#ifdef __SIZEOF_INT128__
151-
template <> struct make_unsigned<__int128_t> {
152-
using type = __uint128_t;
153-
};
154-
template <> struct make_unsigned<__uint128_t> {
155-
using type = __uint128_t;
156-
};
135+
template <> struct make_unsigned<__int128_t> { using type = __uint128_t; };
136+
template <> struct make_unsigned<__uint128_t> { using type = __uint128_t; };
157137
#endif
158138
template <typename T> using make_unsigned_t = typename make_unsigned<T>::type;
159139

libc/test/src/__support/CPP/span_test.cpp

+10
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,16 @@ TEST(LlvmLibcSpanTest, InitializeArray) {
5656
ASSERT_EQ(s[2], 3);
5757
}
5858

59+
TEST(LlvmLibcSpanTest, ConstFromMutable) {
60+
array<int, 3> a = {1, 2, 3};
61+
span<int> mutable_view(a);
62+
span<const int> const_view(mutable_view);
63+
ASSERT_EQ(const_view.size(), size_t(3));
64+
ASSERT_EQ(const_view[0], 1);
65+
ASSERT_EQ(const_view[1], 2);
66+
ASSERT_EQ(const_view[2], 3);
67+
}
68+
5969
TEST(LlvmLibcSpanTest, Modify) {
6070
int a[] = {1, 2, 3};
6171
span<int> s(a);

0 commit comments

Comments
 (0)