@@ -59,6 +59,8 @@ template <typename measure_type>
5959class re_measurement
6060{
6161public:
62+ using value_type = std::remove_cv_t <measure_type>;
63+
6264 // / Default destructor
6365 virtual ~re_measurement () = default ;
6466
@@ -80,12 +82,42 @@ class re_measurement
8082};
8183
8284// / \brief Modular resource element measurement.
85+ // /
86+ // / A modular resource element is a collection of views to symbols organized in slices. All symbols must have the same
87+ // / size (number of subcarriers).
88+ // /
89+ // / A \c modular_re_measurement object can be created from another \c re_measurement-based object, for instance to
90+ // / restrict access to a subset of subcarriers. The constructor preserves the const-qualification of the original object
91+ // / (e.g., a read-only \c re_measurement generates a read-only \c modular_re_measurement).
92+ // /
8393// / \tparam measure_type Underlying data type.
84- // / \tparam MaxNofSymbols Maximum number of symbols.
94+ // / \tparam MaxNofSymbols Maximum number of symbols per slice .
8595// / \tparam MaxNofSlices Maximum number of slices.
8696template <typename measure_type, unsigned MaxNofSymbols, unsigned MaxNofSlices>
8797class modular_re_measurement : public re_measurement <measure_type>
8898{
99+ private:
100+ // / Metaprogramming for checking types in the constructors.
101+ // /@{
102+ // / Default failing compatibility test.
103+ template <typename T, typename = void >
104+ struct is_modular_compatible : std::false_type {};
105+
106+ // / \brief Compatibility test for type \c T.
107+ // /
108+ // / Type T can be used to construct a modular_re_measurement<measure_type> object if re_measurement is the base class
109+ // / of T and if we can create span<measure_type> from span<T::value_type>.
110+ template <typename T>
111+ struct is_modular_compatible <T, std::void_t <typename T::value_type>>
112+ : std::conditional_t <
113+ std::is_base_of_v<re_measurement<typename T::value_type>, T> &&
114+ std::is_convertible_v<
115+ std::conditional_t <std::is_const_v<T>, const typename T::value_type, typename T::value_type> (*)[],
116+ measure_type (*)[]>,
117+ std::true_type,
118+ std::false_type> {};
119+ // /@}
120+
89121public:
90122 // / Default constructor - creates an empty RE measurement object.
91123 modular_re_measurement () = default;
@@ -94,13 +126,15 @@ class modular_re_measurement : public re_measurement<measure_type>
94126 modular_re_measurement (const re_measurement_dimensions& dimensions_) { resize (dimensions_); }
95127
96128 // / Creates a modular RE measurement object from another RE measurement object.
97- modular_re_measurement (re_measurement<measure_type>& other) : modular_re_measurement(other, 0 , other.size().nof_subc)
129+ template <typename U, std::enable_if_t <is_modular_compatible<U>::value, int > = 0 >
130+ modular_re_measurement (U& other) : modular_re_measurement(other, 0 , other.size().nof_subc)
98131 {
99132 }
100133
101134 // / Creates a modular RE measurement object from another RE measurement object with an offset and number of
102135 // / subcarriers.
103- modular_re_measurement (re_measurement<measure_type>& other, unsigned offset, unsigned nof_subc)
136+ template <typename U, std::enable_if_t <is_modular_compatible<U>::value, int > = 0 >
137+ modular_re_measurement (U& other, unsigned offset, unsigned nof_subc)
104138 {
105139 assign (other, offset, nof_subc);
106140 }
@@ -152,8 +186,12 @@ class modular_re_measurement : public re_measurement<measure_type>
152186 std::fill_n (data.get_data ().begin (), dims.nof_slices * dims.nof_symbols , span<measure_type>());
153187 }
154188
155- // / Sets a symbol view.
156- void set_symbol (unsigned i_symbol, unsigned i_slice, span<measure_type> view)
189+ // / \brief Sets a symbol view.
190+ // /
191+ // / This method is available only if a view <t>span<U></t> is compatible with the data type of the RE measurements
192+ // / stored in the calling object.
193+ template <typename U, std::enable_if_t <std::is_convertible_v<U (*)[], measure_type (*)[]>, int > = 0 >
194+ void set_symbol (unsigned i_symbol, unsigned i_slice, span<U> view)
157195 {
158196 srsran_assert (i_slice < dimensions.nof_slices ,
159197 " Slice index (i.e., {}) exceeds the number of slices (i.e., {})." ,
@@ -171,10 +209,15 @@ class modular_re_measurement : public re_measurement<measure_type>
171209 }
172210
173211 // / Assigns the views of the resource element measurement to another measurement.
174- void assign (re_measurement<measure_type>& other) { assign (other, 0 , other.size ().nof_subc ); }
212+ template <typename U, std::enable_if_t <is_modular_compatible<U>::value, int > = 0 >
213+ void assign (U& other)
214+ {
215+ assign (other, 0 , other.size ().nof_subc );
216+ }
175217
176218 // / Assigns the views of the resource element measurement to another measurement with a subcarrier offset.
177- void assign (re_measurement<measure_type>& other, unsigned offset, unsigned nof_subc)
219+ template <typename U, std::enable_if_t <is_modular_compatible<U>::value, int > = 0 >
220+ void assign (U& other, unsigned offset, unsigned nof_subc)
178221 {
179222 const re_measurement_dimensions& base_dims = other.size ();
180223 srsran_assert (offset + nof_subc <= base_dims.nof_subc , " Invalid offset and number of subcarriers." );
@@ -191,8 +234,7 @@ class modular_re_measurement : public re_measurement<measure_type>
191234private:
192235 re_measurement_dimensions dimensions;
193236 static_tensor<2 , span<measure_type>, MaxNofSymbols * MaxNofSlices> data;
194-
195- }; // namespace srsran
237+ };
196238
197239namespace detail {
198240
@@ -322,16 +364,16 @@ class static_re_measurement
322364 // / Constructor: checks template type.
323365 static_re_measurement ()
324366 {
325- static_assert (std::is_same <measure_type, float >::value || std::is_same <measure_type, cf_t >::value ||
326- std::is_same <measure_type, cbf16_t >::value ,
367+ static_assert (std::is_same_v <measure_type, float > || std::is_same_v <measure_type, cf_t > ||
368+ std::is_same_v <measure_type, cbf16_t >,
327369 " At the moment, this template is only available for float, cf_t and cbf16_t." );
328370 base::reserved_dims = {MAX_NOF_SUBC, MAX_NOF_SYMBOLS, MAX_NOF_SLICES};
329371 }
330372
331373 // / Constructor: sets the size of the internal buffer.
332374 explicit static_re_measurement (const re_measurement_dimensions& dims) : static_re_measurement()
333375 {
334- static_assert (std::is_same <measure_type, float >::value || std::is_same <measure_type, cf_t >::value ,
376+ static_assert (std::is_same_v <measure_type, float > || std::is_same_v <measure_type, cf_t >,
335377 " At the moment, this template is only available for float and cf_t." );
336378 base::resize (dims);
337379 }
@@ -356,7 +398,7 @@ class dynamic_re_measurement
356398 // / Constructor: checks template type and reserves internal memory.
357399 dynamic_re_measurement ()
358400 {
359- static_assert (std::is_same <measure_type, float >::value || std::is_same <measure_type, cf_t >::value ,
401+ static_assert (std::is_same_v <measure_type, float > || std::is_same_v <measure_type, cf_t >,
360402 " At the moment, this template is only available for float and cf_t." );
361403 }
362404
@@ -367,7 +409,7 @@ class dynamic_re_measurement
367409 // / \warning This method entails a heap memory allocation.
368410 void reserve (const re_measurement_dimensions& dims)
369411 {
370- static_assert (std::is_same <measure_type, float >::value || std::is_same <measure_type, cf_t >::value ,
412+ static_assert (std::is_same_v <measure_type, float > || std::is_same_v <measure_type, cf_t >,
371413 " At the moment, this template is only available for float and cf_t." );
372414
373415 base::reserved_dims = dims;
0 commit comments