Skip to content

Conversation

@rolandreichweinbmw
Copy link
Collaborator

This commit adds to etl::span:

  • advance()
  • copy()
  • reinterpret_as()

including tests.

@jwellbelove
Copy link
Contributor

Is the purpose of reinterpret_as to map, for example, a buffer of char to a range of int, and the other way round?
Shouldn't there to be a check for size multiple and possibly alignment, so that, say, seven int8_t at an odd alignment cannot be reinterpreted as a unit32_t?

i.e.

etl::array<int8_t, 7> buffer;
etl::span<int8_t) sp1(buffer.begin(), buffer.end());
auto sp2 = sp1.reinterpret_as<unit32_t>();

uint32_t i = *sp2.begin(); // Is this aligned correctly!

@rolandreichweinbmw
Copy link
Collaborator Author

Right. I will add this.

template <typename T1, size_t N1, typename T2, size_t N2>
typename etl::enable_if<etl::is_same<typename etl::remove_cv<T1>::type, typename etl::remove_cv<T2>::type>::value &&
!etl::is_const<T2>::value, bool>::type
copy(const etl::span<T1, N1>& src, const etl::span<T2, N2>& dst)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a class member function, but it copies between two other spans.
This would be better implemented as a separate standalone function, or maybe as a member copy_to(dst)

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you sure?

As far as I can see, this free function etl::copy(), actually an overload, is outside the class, similar to the directly above etl::equal().

What is strange here is the line numbering. When I merge it on top of current master, it ends up in l.968, not l.830.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, I see that it is already a standalone function. I got confused looking at diff view late last night. It made the copy function look like a member of the class.
I looked at the full file view this morning.

ETL_NODISCARD ETL_CONSTEXPR14 etl::span<TNew, etl::dynamic_extent> reinterpret_as() const
{
#if ETL_USING_CPP11
ETL_ASSERT(etl::is_aligned<alignof(TNew)>(pbegin), ETL_ERROR(span_alignment_exception));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can use etl::alignment_of instead of alignof which works for C++03.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the hint! Updating it accordingly.

@rolandreichweinbmw rolandreichweinbmw force-pushed the span-advance-copy-reinterpret-as branch from 53b3752 to bbb58b9 Compare March 2, 2025 20:04
@rolandreichweinbmw
Copy link
Collaborator Author

Regarding your remark about odd-numbered spans where you get rounding errors when reinterpreting: This is intended, and considered a feature. Consider the case of having a buffer from some protocol data, and only a part of it is the respective span, i.e. value array. Then the size is automatically rounded down to the next correct size, and we can only correctly assume the initial whole elements to be valid, and discard the rest:

  • "If pend - pbegin is 3 bytes and TNew is an int32_t then the size of the new span is 0." - Yes, as expected.
  • "If pend - pbegin is 6 bytes and TNew is an int32_t then the size of the new span is 1, with 2 bytes before pend." - Yes, as expected
  • "An advance of the int32_t span pbegin pointer would never equal pend, meaning loops of the return span would never terminate." - No, because the expected new size 1 leads to pbegin and pend to be set correctly, with pend discarding the bytes you mentioned in the first 2 cases.

I added further unit tests for reinterpret_as() to show what I mean.

@jwellbelove
Copy link
Contributor

Yes, I realised that after I wrote the comment. I deleted the comment.

Multiple inheritance leads to additional 1 byte for the second base class.
Fixing it by not inheriting but aggregating via typedef.
@rolandreichweinbmw rolandreichweinbmw force-pushed the span-advance-copy-reinterpret-as branch from 12c07f7 to f8a70ed Compare March 2, 2025 21:48
@rolandreichweinbmw
Copy link
Collaborator Author

After rebasing onto latest ETL with new unaligned_type, I encountered failing unit tests for reinterpret_as() on Windows.

It was caused by the new multiple inheritance of unaligned_type because sizeof() now results in additional bytes counted for the second base class unaligned_copy which contributed an additional byte. (Even though empty class - but looks like 1 byte is reserved for that.)

My solution in the branch is the change to single inheritance, moving unaligned_copy to a class member typedef. Including tests for that.

@jwellbelove jwellbelove changed the base branch from master to pull-request/#1024-etl-span-Add-advance(),-copy(),-reinterpret_as() March 3, 2025 08:52
@jwellbelove jwellbelove merged commit d5bea3a into ETLCPP:pull-request/#1024-etl-span-Add-advance(),-copy(),-reinterpret_as() Mar 3, 2025
63 checks passed
jwellbelove pushed a commit that referenced this pull request Mar 3, 2025
* etl::span: Add advance(), copy(), reinterpret_as()

* Added further tests for span::reinterpret_as

* Fix size of unaligned_type on Windows

Multiple inheritance leads to additional 1 byte for the second base class.
Fixing it by not inheriting but aggregating via typedef.
jwellbelove pushed a commit that referenced this pull request Mar 3, 2025
…terpret_as()' of https://github.com/ETLCPP/etl into pull-request/#1024-etl-span-Add-advance(),-copy(),-reinterpret_as()

# Conflicts:
#	include/etl/span.h
jwellbelove pushed a commit that referenced this pull request Mar 28, 2025
* etl::span: Add advance(), copy(), reinterpret_as()

* Added further tests for span::reinterpret_as

* Fix size of unaligned_type on Windows

Multiple inheritance leads to additional 1 byte for the second base class.
Fixing it by not inheriting but aggregating via typedef.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants