- Simplified the usage of span now with implicit constructors as it should be.

- Added overload for generic containers that have size and data members like vector.
- Removed unnecessary uses of make_span.
This commit is contained in:
faluco 2020-08-11 11:50:15 +02:00 committed by Francisco Paisana
parent 158edd4fe7
commit 072e84cec8
4 changed files with 70 additions and 51 deletions

View File

@ -33,12 +33,53 @@ namespace srslte {
/// The class template span describes an object that can refer to a contiguous sequence of objects with the first
/// element of the sequence at position zero.
/// It is encouraged to use the make_span() helper functions for creating new spans instead of using the constructors
/// directly. This way is more explicit in code and makes the developer think first to make sure the lifetime of the
/// sequence outlasts the new created span.
template <typename T>
class span
{
/// Helper traits used by SFINAE expressions in constructors.
template <typename... Ts>
struct make_void {
typedef void type;
};
template <typename... Ts>
using void_t = typename make_void<Ts...>::type;
template <typename U>
struct is_span : std::false_type {};
template <typename U>
struct is_span<span<U> > : std::true_type {};
template <typename U>
struct is_std_array : std::false_type {};
template <typename U, std::size_t N>
struct is_std_array<std::array<U, N> > : std::true_type {};
template <typename U>
using remove_cvref_t = typename std::remove_cv<typename std::remove_reference<U>::type>::type;
template <class Container, class U, class = void>
struct is_container_compatible : public std::false_type {};
template <class Container, class U>
struct is_container_compatible<
Container,
U,
void_t<
// Check if the container type has data and size members.
decltype(std::declval<Container>().data()),
decltype(std::declval<Container>().size()),
// Container should not be a span.
typename std::enable_if<!is_span<remove_cvref_t<Container> >::value, int>::type,
// Container should not be a std::array.
typename std::enable_if<!is_std_array<remove_cvref_t<Container> >::value, int>::type,
// Container should not be an array.
typename std::enable_if<!std::is_array<remove_cvref_t<Container> >::value, int>::type,
// Check type compatibility between the contained type and the span type.
typename std::enable_if<
std::is_convertible<typename std::remove_pointer<decltype(std::declval<Container>().data())>::type (*)[],
U (*)[]>::value,
int>::type> > : public std::true_type {};
public:
/// Member types.
using element_type = T;
@ -56,10 +97,10 @@ public:
constexpr span() noexcept = default;
/// Constructs a span that is a view over the range [ptr, ptr + len).
constexpr explicit span(pointer ptr, size_type len) noexcept : ptr(ptr), len(len) {}
constexpr span(pointer ptr, size_type len) noexcept : ptr(ptr), len(len) {}
/// Constructs a span that is a view over the range [first, last).
constexpr explicit span(pointer first, pointer last) noexcept : ptr(first), len(last - first) {}
constexpr span(pointer first, pointer last) noexcept : ptr(first), len(last - first) {}
/// Constructs a span that is a view over the array arr.
template <std::size_t N>
@ -80,6 +121,18 @@ public:
constexpr span(const std::array<U, N>& arr) noexcept : ptr(arr.data()), len(N)
{}
/// Constructs a span that is a view over the container c.
template <typename Container,
typename std::enable_if<is_container_compatible<Container, element_type>::value, int>::type = 0>
constexpr span(Container& c) noexcept : ptr(c.data()), len(c.size())
{}
/// Constructs a span that is a view over the container c.
template <typename Container,
typename std::enable_if<is_container_compatible<const Container, element_type>::value, int>::type = 0>
constexpr span(const Container& c) noexcept : ptr(c.data()), len(c.size())
{}
template <typename U, typename std::enable_if<std::is_convertible<U (*)[], element_type (*)[]>::value, int>::type = 0>
constexpr span(const span<U>& other) noexcept : ptr(other.data()), len(other.size())
{}
@ -156,7 +209,7 @@ public:
span<element_type> subspan(size_type offset, size_type count) const
{
assert(count <= size() - offset && "size out of bounds!");
return span{data() + offset, count};
return {data() + offset, count};
}
/// Returns true if the input span has the same elements as this.
@ -179,40 +232,6 @@ inline bool operator!=(span<T> lhs, span<T> rhs)
return not lhs.equals(rhs);
}
///
/// Helpers to construct span objects from different types of contiguous containers.
///
template <typename T, std::size_t N>
inline span<T> make_span(T (&arr)[N])
{
return span<T>{arr};
}
template <typename T, std::size_t N>
inline span<T> make_span(std::array<T, N>& arr)
{
return span<T>{arr};
}
template <typename T, std::size_t N>
inline span<const T> make_span(const std::array<T, N>& arr)
{
return span<const T>{arr};
}
template <typename T>
inline span<T> make_span(std::vector<T>& v)
{
return span<T>{v.data(), v.size()};
}
template <typename T>
inline span<const T> make_span(const std::vector<T>& v)
{
return span<const T>{v.data(), v.size()};
}
} // namespace srslte
#endif // SRSLTE_SPAN_H

View File

@ -27,7 +27,7 @@ int test_span_access()
std::array<int, 7> values{1, 2, 3, 4, 5, 6, 7};
{
auto view = srslte::make_span(values);
srslte::span<int> view = values;
// access operators
TESTASSERT(view.size() == 7);
@ -56,7 +56,7 @@ int test_span_conversion()
{
// TEST: changing individual values
auto v = srslte::make_span(values), v2 = srslte::make_span(values2);
srslte::span<int> v = values, v2 = values2;
TESTASSERT(v == v2);
v[0] = 3;
@ -68,7 +68,7 @@ int test_span_conversion()
{
// TEST: const context
const auto v = srslte::make_span(values), v2 = srslte::make_span(values2);
const srslte::span<int> v = values, v2 = values2;
TESTASSERT(v != v2);
TESTASSERT(v[0] == 3);
TESTASSERT(v2[0] == 2);
@ -78,8 +78,8 @@ int test_span_conversion()
{
// TEST: raw arrays
int carray[] = {2, 3, 4, 5, 6, 7, 8};
auto v = srslte::make_span(values), v2 = srslte::make_span(carray);
int carray[] = {2, 3, 4, 5, 6, 7, 8};
srslte::span<int> v = values, v2 = carray;
TESTASSERT(v == v2);
TESTASSERT(v2.size() == v.size());
}

View File

@ -430,7 +430,7 @@ int test_s1ap_mobility(mobility_test_params test_params)
0x01, 0x48, 0x04, 0xbc, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x02, 0xa0, 0x07, 0xa0,
0x10, 0x00, 0x01, 0x00, 0x05, 0x00, 0xa7, 0xd0, 0xc1, 0xf6, 0xaf, 0x3e, 0x12, 0xcc,
0x86, 0x0d, 0x30, 0x00, 0x0b, 0x5a, 0x02, 0x17, 0x86, 0x00, 0x05, 0xa0, 0x20};
test_helpers::copy_msg_to_buffer(pdu, srslte::make_span(ho_cmd_rrc_container));
test_helpers::copy_msg_to_buffer(pdu, ho_cmd_rrc_container);
TESTASSERT(s1ap.last_enb_status.rnti != tester.rnti);
tester.rrc.ho_preparation_complete(tester.rnti, true, std::move(pdu));
TESTASSERT(s1ap.last_enb_status.status_present);

View File

@ -228,7 +228,7 @@ int bring_rrc_to_reconf_state(srsenb::rrc& rrc, srslte::timer_handler& timers, u
// Send RRCConnectionRequest
uint8_t rrc_conn_request[] = {0x40, 0x12, 0xf6, 0xfb, 0xe2, 0xc6};
copy_msg_to_buffer(pdu, srslte::make_span(rrc_conn_request));
copy_msg_to_buffer(pdu, rrc_conn_request);
rrc.write_pdu(rnti, 0, std::move(pdu));
timers.step_all();
rrc.tti_clock();
@ -237,7 +237,7 @@ int bring_rrc_to_reconf_state(srsenb::rrc& rrc, srslte::timer_handler& timers, u
uint8_t rrc_conn_setup_complete[] = {0x20, 0x00, 0x40, 0x2e, 0x90, 0x50, 0x49, 0xe8, 0x06, 0x0e, 0x82, 0xa2,
0x17, 0xec, 0x13, 0xe2, 0x0f, 0x00, 0x02, 0x02, 0x5e, 0xdf, 0x7c, 0x58,
0x05, 0xc0, 0xc0, 0x00, 0x08, 0x04, 0x03, 0xa0, 0x23, 0x23, 0xc0};
copy_msg_to_buffer(pdu, srslte::make_span(rrc_conn_setup_complete));
copy_msg_to_buffer(pdu, rrc_conn_setup_complete);
rrc.write_pdu(rnti, 1, std::move(pdu));
timers.step_all();
rrc.tti_clock();
@ -267,7 +267,7 @@ int bring_rrc_to_reconf_state(srsenb::rrc& rrc, srslte::timer_handler& timers, u
// Send SecurityModeComplete
uint8_t sec_mode_complete[] = {0x28, 0x00};
copy_msg_to_buffer(pdu, srslte::make_span(sec_mode_complete));
copy_msg_to_buffer(pdu, sec_mode_complete);
rrc.write_pdu(rnti, 1, std::move(pdu));
timers.step_all();
rrc.tti_clock();
@ -275,14 +275,14 @@ int bring_rrc_to_reconf_state(srsenb::rrc& rrc, srslte::timer_handler& timers, u
// send UE cap info
uint8_t ue_cap_info[] = {0x38, 0x01, 0x01, 0x0c, 0x98, 0x00, 0x00, 0x18, 0x00, 0x0f,
0x30, 0x20, 0x80, 0x00, 0x01, 0x00, 0x0e, 0x01, 0x00, 0x00};
copy_msg_to_buffer(pdu, srslte::make_span(ue_cap_info));
copy_msg_to_buffer(pdu, ue_cap_info);
rrc.write_pdu(rnti, 1, std::move(pdu));
timers.step_all();
rrc.tti_clock();
// RRCConnectionReconfiguration was sent. Send RRCConnectionReconfigurationComplete
uint8_t rrc_conn_reconf_complete[] = {0x10, 0x00};
copy_msg_to_buffer(pdu, srslte::make_span(rrc_conn_reconf_complete));
copy_msg_to_buffer(pdu, rrc_conn_reconf_complete);
rrc.write_pdu(rnti, 1, std::move(pdu));
timers.step_all();
rrc.tti_clock();