Skip to content

Conversation

@tmadlener
Copy link
Collaborator

@tmadlener tmadlener commented Jan 14, 2026

original outset of this PR: non-const collections give access to mutable handles via operator[] and at(). Hence, they should also model ranges over mutable handles. The fix is straight forward: Make sure the iterators report the correct value_type.

See the discussion below for why we now make the link collections behave the same as the generated ones.

BEGINRELEASENOTES

  • Make the LinkCollectionIteratorT::value_type an immutable Link always for consistency with the behavior of generated collection iterators.

ENDRELEASENOTES

@m-fila am I missing something obvious here?

Copy link
Contributor

@m-fila m-fila left a comment

Choose a reason for hiding this comment

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

We had value_type in iterators defined to immutable type to fulfill some of the "Container" requirements.

We already don't fulfill "Container" for a number of reasons, so it should be fine to break it slightly more as long as we don't break requirements for iterators and ranges (which aren't affected by it)

@tmadlener
Copy link
Collaborator Author

Right, so some nuances still here. We don't really change any behavior that allows to break things that weren't already broken before, I think.

Just to confirm, the main thing that now is possible that wasn't before is this:

ExampleClusterCollection coll{};
for (auto& elem : coll) {
  coll.setEnergy(42);  // not possible before because elem would not have a setter
}

One would have to do this (which is also already possible now)

for (size_t i = 0; i < coll.size(); ++i) {
  coll[i].setEnergy(42);  // possible because operator[] returns a mutable handle on non-const collections
}

What is broken regardless of these changes is assigning a new handle to the element, I think. Or does that also change with this change? (Do we have a test for that that I simply missed?).

Anyhow, the main reason I wanted to have this feature, is because it makes it behave the same as the LinkCollection, where we do:

using LinkType = LinkT<FromT, ToT, Mutable>;
using LinkObjT = LinkObj<FromT, ToT>;
public:
using value_type = LinkType;

(i.e. we also have the value_type be different depending on the iterator type). We should make sure this is consistent. I technically don't need this feature, it just makes for a nice example in the tests for #923.

@m-fila
Copy link
Contributor

m-fila commented Jan 14, 2026

Just to confirm, the main thing that now is possible that wasn't before is this:

ExampleClusterCollection coll{};
for (auto& elem : coll) {
  coll.setEnergy(42);  // not possible before because elem would not have a setter
}

Does it compile now? I thought it still shouldn't since operator* for iterator returns temporary mutable dataobject which can't be bound to non-const l-value reference. (unlike for something like std::vector::iterator::operator* which returns real l-value reference)
Using value for (auto elem : coll) or forwarding reference for (auto&& elem : coll) works now and before

What is broken regardless of these changes is assigning a new handle to the element, I think. Or does that also change with this change? (Do we have a test for that that I simply missed?).

This is a separate problem that isn't affected by this PR. Dataobject assignment changes which internal object is held instead of changing members of internal object. For temporaries that was very confusing and made no sense so we disabled it in #743.

(i.e. we also have the value_type be different depending on the iterator type). We should make sure this is consistent. I technically don't need this feature, it just makes for a nice example in the tests for #923.

We could also make it consistent in the other direction: have both immutable and mutable iterators to link collection use immutable type as value_type. I guess the choice is whether meta-programming becomes easier (in #923) or we want to follow some of the conventions from "Container" even though we can't fulfill all of them (and it seems that actual we have so far no code that really depends whether we follow them or not)

@tmadlener
Copy link
Collaborator Author

Just to confirm, the main thing that now is possible that wasn't before is this:

ExampleClusterCollection coll{};
for (auto& elem : coll) {
coll.setEnergy(42);  // not possible before because elem would not have a setter
}

Does it compile now? I thought it still shouldn't since operator* for iterator returns temporary mutable dataobject which can't be bound to non-const l-value reference.

You are correct, it doesn't compile at the moment. But since for (auto elem : coll) works, I think I should be able to work around this in #923 without changing this.

We could also make it consistent in the other direction: have both immutable and mutable iterators to link collection use immutable type as value_type.

Yes, exactly. Looking at the possible can of worms this opens here, I think it would be easier to do that.

@tmadlener tmadlener force-pushed the coll-range-mutability branch from f7ec3a4 to f14ce00 Compare January 15, 2026 09:56
@tmadlener tmadlener changed the title Make non-const collections a range over mutable handles Make link collection iterators behave consistently with generated collection iterators Jan 15, 2026
@m-fila
Copy link
Contributor

m-fila commented Jan 15, 2026

How about we make it requirement in CollectionType concept so all the things claiming to be "collection" check it?

requires std::same_as<typename T::value_type, typename std::iterator_traits<typename T::iterator>::value_type>;
requires std::same_as<typename T::value_type, typename std::iterator_traits<typename T::const_iterator>::value_type>;

non-const collections give access to mutable handles via operator[] and
at(). Hence, they should also model ranges over mutable handles. The fix
is straight forward: Make sure the iterators report the correct
value_type.
Making sure that the value_type of the LinkCollectionIterator is always
an immutable handle since that is what is also done for generated
collections.
@tmadlener tmadlener force-pushed the coll-range-mutability branch from e5cae8a to aadfec1 Compare January 15, 2026 14:07
@tmadlener tmadlener enabled auto-merge (squash) January 15, 2026 14:07
@tmadlener tmadlener merged commit acb77a2 into AIDASoft:master Jan 15, 2026
27 of 28 checks passed
@tmadlener tmadlener deleted the coll-range-mutability branch January 15, 2026 15:59
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