Skip to content

Commit 2c37a3c

Browse files
committed
Added Span for easy C array handling.
1 parent c5a3d67 commit 2c37a3c

File tree

2 files changed

+175
-0
lines changed

2 files changed

+175
-0
lines changed

src/span.tcc

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
template <class T>
2+
class Span {
3+
public:
4+
Span() = default;
5+
6+
/*!
7+
* Create a Span with `n` elements.
8+
*/
9+
template <size_t n>
10+
Span(T (&)[n]);
11+
12+
T& operator [](size_t const);
13+
T const& operator [](size_t const) const;
14+
15+
T* begin();
16+
T* end();
17+
T const* begin() const;
18+
T const* end() const;
19+
20+
/*!
21+
* Get the underlying data.
22+
*
23+
* \return data.
24+
*/
25+
T* data() const;
26+
27+
/*!
28+
* Get the number of elements.
29+
*
30+
* \return Span size.
31+
*/
32+
size_t size() const;
33+
34+
private:
35+
T* data_ {};
36+
size_t size_ {};
37+
};
38+
39+
40+
template <class T>
41+
template <size_t n>
42+
Span<T>::Span(T (&a)[n]) : data_ {a}, size_ {n} {}
43+
44+
45+
template <class T>
46+
T& Span<T>::operator [](size_t const idx) {
47+
return data_[idx];
48+
}
49+
50+
template <class T>
51+
T const& Span<T>::operator [](size_t const idx) const {
52+
return data_[idx];
53+
}
54+
55+
56+
template <class T>
57+
T* Span<T>::begin() {
58+
return data_;
59+
}
60+
61+
template <class T>
62+
T* Span<T>::end() {
63+
return data_ + size_;
64+
}
65+
66+
template <class T>
67+
T const* Span<T>::begin() const {
68+
return data_;
69+
}
70+
71+
template <class T>
72+
T const* Span<T>::end() const {
73+
return data_ + size_;
74+
}
75+
76+
77+
template <class T>
78+
T* Span<T>::data() const {
79+
return data_;
80+
}
81+
82+
template <class T>
83+
size_t Span<T>::size() const {
84+
return size_;
85+
}

tests/test_span.cc

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
#include <catch.hpp>
2+
3+
#include "../src/span.tcc"
4+
5+
6+
TEST_CASE("Span initialisation.", "[span]") {
7+
int data[] {1, 2, 3};
8+
Span<int> s {data};
9+
10+
REQUIRE(s.size() == 3);
11+
REQUIRE(s[1] == 2);
12+
}
13+
14+
TEST_CASE("Span set and get elements.", "[span]") {
15+
int data[2] {};
16+
Span<int> s {data};
17+
18+
data[0] = 1234;
19+
data[1] = 2345;
20+
21+
REQUIRE(s.size() == 2);
22+
REQUIRE(s[0] == 1234);
23+
REQUIRE(s[1] == 2345);
24+
}
25+
26+
TEST_CASE("Span get constant elements.", "[span]") {
27+
int const data[] {1234, 2345};
28+
Span<int const> const s {data};
29+
30+
REQUIRE(s.size() == 2);
31+
REQUIRE(s[0] == 1234);
32+
REQUIRE(s[1] == 2345);
33+
}
34+
35+
36+
TEST_CASE("Span range loop.", "[span]") {
37+
int data[2] {};
38+
Span<int> s {data};
39+
40+
for (int& el: s) {
41+
el = 1234;
42+
}
43+
for (int const& el: s) {
44+
REQUIRE(el == 1234);
45+
}
46+
}
47+
48+
49+
TEST_CASE("Span data.", "[span]") {
50+
int data[2] {};
51+
Span<int> s {data};
52+
53+
REQUIRE(s.data() == data);
54+
}
55+
56+
TEST_CASE("Span size.", "[span]") {
57+
int data[2] {};
58+
Span<int> s {data};
59+
60+
REQUIRE(s.size() == 2);
61+
}
62+
63+
64+
TEST_CASE("Span return.", "[span]") {
65+
struct S {
66+
static Span<int> f() {
67+
static int data[] {1234, 2345};
68+
Span<int> s {data};
69+
return s;
70+
}
71+
};
72+
73+
Span<int> s {};
74+
s = S::f();
75+
76+
REQUIRE(s[0] == 1234);
77+
}
78+
79+
TEST_CASE("Span pass by value.", "[span]") {
80+
struct S {
81+
static void f(Span<int> s) {
82+
REQUIRE(s.size() == 2);
83+
REQUIRE(s[0] == 1234);
84+
}
85+
};
86+
87+
int data[] {1234, 2345};
88+
Span<int> s {data};
89+
S::f(s);
90+
}

0 commit comments

Comments
 (0)