diff --git a/lib/include/srslte/adt/span.h b/lib/include/srslte/adt/span.h index ab48ca126..0ea409a78 100644 --- a/lib/include/srslte/adt/span.h +++ b/lib/include/srslte/adt/span.h @@ -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 class span { + /// Helper traits used by SFINAE expressions in constructors. + + template + struct make_void { + typedef void type; + }; + template + using void_t = typename make_void::type; + + template + struct is_span : std::false_type {}; + template + struct is_span > : std::true_type {}; + + template + struct is_std_array : std::false_type {}; + template + struct is_std_array > : std::true_type {}; + + template + using remove_cvref_t = typename std::remove_cv::type>::type; + + template + struct is_container_compatible : public std::false_type {}; + template + struct is_container_compatible< + Container, + U, + void_t< + // Check if the container type has data and size members. + decltype(std::declval().data()), + decltype(std::declval().size()), + // Container should not be a span. + typename std::enable_if >::value, int>::type, + // Container should not be a std::array. + typename std::enable_if >::value, int>::type, + // Container should not be an array. + typename std::enable_if >::value, int>::type, + // Check type compatibility between the contained type and the span type. + typename std::enable_if< + std::is_convertible().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 @@ -80,6 +121,18 @@ public: constexpr span(const std::array& arr) noexcept : ptr(arr.data()), len(N) {} + /// Constructs a span that is a view over the container c. + template ::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 ::value, int>::type = 0> + constexpr span(const Container& c) noexcept : ptr(c.data()), len(c.size()) + {} + template ::value, int>::type = 0> constexpr span(const span& other) noexcept : ptr(other.data()), len(other.size()) {} @@ -156,7 +209,7 @@ public: span 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 lhs, span rhs) return not lhs.equals(rhs); } -/// -/// Helpers to construct span objects from different types of contiguous containers. -/// - -template -inline span make_span(T (&arr)[N]) -{ - return span{arr}; -} - -template -inline span make_span(std::array& arr) -{ - return span{arr}; -} - -template -inline span make_span(const std::array& arr) -{ - return span{arr}; -} - -template -inline span make_span(std::vector& v) -{ - return span{v.data(), v.size()}; -} - -template -inline span make_span(const std::vector& v) -{ - return span{v.data(), v.size()}; -} - } // namespace srslte #endif // SRSLTE_SPAN_H diff --git a/lib/test/adt/span_test.cc b/lib/test/adt/span_test.cc index e821081f9..58305ee82 100644 --- a/lib/test/adt/span_test.cc +++ b/lib/test/adt/span_test.cc @@ -27,7 +27,7 @@ int test_span_access() std::array values{1, 2, 3, 4, 5, 6, 7}; { - auto view = srslte::make_span(values); + srslte::span 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 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 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 v = values, v2 = carray; TESTASSERT(v == v2); TESTASSERT(v2.size() == v.size()); } diff --git a/srsenb/test/upper/rrc_mobility_test.cc b/srsenb/test/upper/rrc_mobility_test.cc index 494b53f58..11de7014a 100644 --- a/srsenb/test/upper/rrc_mobility_test.cc +++ b/srsenb/test/upper/rrc_mobility_test.cc @@ -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); diff --git a/srsenb/test/upper/test_helpers.h b/srsenb/test/upper/test_helpers.h index 40c237955..b9c8acc76 100644 --- a/srsenb/test/upper/test_helpers.h +++ b/srsenb/test/upper/test_helpers.h @@ -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();