Skip to content

Improve Container Types #180

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 25 commits into
base: master
Choose a base branch
from
Open

Improve Container Types #180

wants to merge 25 commits into from

Conversation

Mozz3d
Copy link
Contributor

@Mozz3d Mozz3d commented Feb 7, 2025

No description provided.

Comment on lines 261 to 263
if (aSize > Capacity())
Reserve(aSize);

Copy link
Owner

Choose a reason for hiding this comment

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

Suggested change
if (aSize > Capacity())
Reserve(aSize);
if (aSize > Capacity())
{
Reserve(aSize);
}

@Mozz3d Mozz3d requested review from WSSDude, wopss and psiberx February 14, 2025 06:34
- Fixed issues
- Added more methods (Erase, Insert, etc.)
- Refactored various methods
- Improved semantics
- Generally cleaned up
@Mozz3d Mozz3d requested a review from psiberx February 20, 2025 17:42
@Mozz3d Mozz3d requested a review from psiberx May 21, 2025 23:51
@WSSDude
Copy link
Collaborator

WSSDude commented May 24, 2025

Id still like to have a look if I may


DynArray& operator=(DynArray&& aOther) noexcept
{
if (this != std::addressof(aOther))
Copy link
Collaborator

Choose a reason for hiding this comment

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

Why not simply swap contents for moving ops btw? Should be cleaner and shorter code overall. Also no need to check for this etc. in such instance.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I believe it was @wopss who wanted it this way, as it doesn't introduce any complexity

Copy link
Owner

Choose a reason for hiding this comment

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

I don't remember complaining about this. I also don't get why we don't do std::swap.

}

auto distance = std::distance(aFirst, aLast);
DifferenceType newSize = std::abs(distance);
Copy link
Collaborator

Choose a reason for hiding this comment

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

I dont like allowing negative values, shouldnt be the case for proper range. Only case this should ever return negative is for random access range where you swapped first and last, shouldnt affect reverse iterators on the range AFAIK.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Im actually unsure if we should even care for distance, IMO for generic case like this when iterators/range isnt random access, it should just use back_inserter, this may introduce tons of unwanted overhead. Iteration over some types isnt fast, and iterating through it twice unnecessarily may bottleneck things unless it is random access range as mentioned.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

How do you suggest I avoid the double evaluation?
I assume it involves changing the template concept to std::forward_iterator?

Copy link
Collaborator

Choose a reason for hiding this comment

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

No, use std::back_inserter instead of directly using begin/end for copying. And preallocate space only when you have std::random_access_iterator via reserving and not resizing. For std::random_access_iterator, std::distance is constant operation.

}

template<std::input_iterator InputIt>
void Assign(InputIt aFirst, InputIt aLast)
Copy link
Collaborator

Choose a reason for hiding this comment

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

Im missing some way to assign range directly, we are long past the age of having to use iterators unless absolutely necessary. Can achieve practically everything with ranges and views more cleanly.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Applies to constructors also.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Missing some move-assignment.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

What are you suggesting here? Should I create a new method to accept a range, or adjust this one? If it's the former, what structures are implied by ranges and views?

Copy link
Collaborator

@WSSDude WSSDude May 26, 2025

Choose a reason for hiding this comment

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

New method ideally which accepts any range as a type. Ranges have to have begin() and end() defined, other functions like empty() and size() are not guaranteed unless you go to specializations of ranges.

It likely would end up as a wrapper for iterator-based assignments.


void PushBack(ConstReference aItem)
{
EmplaceBack(std::forward<ConstReference>(aItem));
Copy link
Collaborator

Choose a reason for hiding this comment

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

I dont think std::forward is correct in this instance. Likely wont cause an issue but that is more thanks to its definition, shouldnt be ever needed when you know you are passing lvalue reference.


void PushBack(ValueType&& aItem)
{
EmplaceBack(std::forward<ValueType&&>(aItem));
Copy link
Collaborator

Choose a reason for hiding this comment

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

This almost certainly seems wrong, forwarding && will always result in rvalue reference even when it formerly wasnt. Just ValueType should be enough.

Copy link
Owner

Choose a reason for hiding this comment

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

I don't even see the need of std::forward here, a simple std::move should be enough.

{
assert(aPos < End() && Includes(aPos));

aPos->~ValueType();
Copy link
Collaborator

Choose a reason for hiding this comment

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

std::destroy_at


[[nodiscard]] constexpr SizeType MaxSize() const noexcept
{
#undef max // avoid conflict with minmax
Copy link
Collaborator

Choose a reason for hiding this comment

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

This shouldnt be needed provided NOMINMAX macro is correctly defined. And if you are worrying about this, rather wrap min and max keywords in parenthesis eg. std::numeric_limits<SizeType>::(max)()

Copy link
Owner

Choose a reason for hiding this comment

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

I would be against providing NOMINMAX macro since others might not like it when this library is used in their code.

template<std::input_iterator InputIt>
StaticArray(InputIt aFirst, InputIt aLast)
{
if (std::distance(aFirst, aLast) > MaxSize())
Copy link
Collaborator

@WSSDude WSSDude May 26, 2025

Choose a reason for hiding this comment

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

And here you dont check the size and make it absolute and whatnot. Just as a note to the other distance comment I had, negative values are practically never a good sign.

Copy link
Owner

Choose a reason for hiding this comment

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

I just thought about this, but removing this header and class will cause a lot of issues. So, I propose to add it back, deprecate them (the header and the class).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

What kind of issues? The changes already include updates to all the DynArray file paths, and Reflection-inl.hpp was updated accordingly for the dumper

Copy link
Owner

Choose a reason for hiding this comment

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

People project's still use this path, changing it like that will be a breaking change.

Copy link
Collaborator

@WSSDude WSSDude May 28, 2025

Choose a reason for hiding this comment

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

Simplest solution to this - just have file in original location including the file from right location.

Isnt likely as clean, but should be more than sufficient imo not @wopss ?
Also the least amount of additional changes.

Copy link
Owner

Choose a reason for hiding this comment

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

Exactly. And add a pragma message in the header saying that it is deprecated.

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.

4 participants