Skip to content

Prototype __tuple_for_each and __tuple_apply for zip_view#2613

Open
kboyarinov wants to merge 218 commits intomainfrom
dev/kboyarinov/zip_view_apply_to_tuple
Open

Prototype __tuple_for_each and __tuple_apply for zip_view#2613
kboyarinov wants to merge 218 commits intomainfrom
dev/kboyarinov/zip_view_apply_to_tuple

Conversation

@kboyarinov
Copy link
Copy Markdown
Contributor

@kboyarinov kboyarinov commented Mar 12, 2026

No description provided.

MikeDvorskiy and others added 30 commits March 5, 2026 14:27
Co-authored-by: Konstantin Boyarinov <konstantin.boyarinov@intel.com>
Co-authored-by: Konstantin Boyarinov <konstantin.boyarinov@intel.com>
Co-authored-by: Konstantin Boyarinov <konstantin.boyarinov@intel.com>
Co-authored-by: Konstantin Boyarinov <konstantin.boyarinov@intel.com>
Co-authored-by: Konstantin Boyarinov <konstantin.boyarinov@intel.com>
Co-authored-by: Konstantin Boyarinov <konstantin.boyarinov@intel.com>
Co-authored-by: Konstantin Boyarinov <konstantin.boyarinov@intel.com>
Co-authored-by: Konstantin Boyarinov <konstantin.boyarinov@intel.com>
Co-authored-by: Konstantin Boyarinov <konstantin.boyarinov@intel.com>
@MikeDvorskiy MikeDvorskiy marked this pull request as draft March 12, 2026 19:51
@MikeDvorskiy
Copy link
Copy Markdown
Contributor

MikeDvorskiy commented Mar 12, 2026

To tell the truth, I could not notice advantages, it does more or less the same, plus renaming - __tuple_for_each instead of __apply_to_tuple...

@kboyarinov
Copy link
Copy Markdown
Contributor Author

To tell the truth, I could not notice advantages, it does more or less the same, plus renaming - __tuple_for_each instead of __apply_to_tuple...

For me, the main concern was that the usages of __apply_to_tuple were hard to understand without the proper background, mainly due to unnecessary lambdas and return values, and overly general naming. This is what I wanted to address.

In this PR, no extra functions are passed to __tuple_for_each or __tuple_apply, and the return type is specified (and the value is returned) only where it is actually needed.
At least for me, the logic is clearer now, but I don't insist on merging this and let other reviewers decide.

Copy link
Copy Markdown
Contributor

@danhoeflinger danhoeflinger left a comment

Choose a reason for hiding this comment

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

Sorry I ran out of time to look at this in depth.

@MikeDvorskiy
Copy link
Copy Markdown
Contributor

to understand without the proper background

I see..

But, bassically, the background here is quite general - knowledge about std::tuple.
And I would say __apply_to_tuple is closer to the standard std::apply at least.

In any case, this is not an error or an issue. It’s not even about code style — it’s more about a coding approach, which can be subjective.

@kboyarinov
Copy link
Copy Markdown
Contributor Author

But, bassically, the background here is quite general - knowledge about std::tuple. And I would say __apply_to_tuple is closer to the standard std::apply at least.

Only one overload is close to std::apply. The other two usage models differ significantly and require deep knowledge of how __apply_to_tuple is implemented to order to understand what is going on in the functions that use it.
As an example, I have already complained about conversion to zip_iterator, which requires providing an empty lambda that merely broadcasts the argument. Semantically, this is not needed.

In any case, this is not an error or an issue. It’s not even about code style — it’s more about a coding approach, which can be subjective.

I agree that this does not affect correctness. However, in my opinion, it makes the already complex code harder to read, harder to understand, and, accordingly, harder to support.
Again, I'm not insisting on finalizing and merging this, and since we have disagreements on this point, I think other reviewers could help us make the right decision.
@danhoeflinger, what do you think about this?

@danhoeflinger
Copy link
Copy Markdown
Contributor

I think this PR does help make things a bit more clear, but there are some inconsistencies I'll comment on shortly.

I definitely think the naming changes of variables throughout the usage of the helpers is an improvement, rather than generic names like __tr.


template <typename _F, typename _Tuple1, typename _Tuple2, std::size_t... _Ip>
void
__tuples_apply_impl(_F __f, _Tuple1& __t1, _Tuple2& __t2, std::index_sequence<_Ip...>)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Should this be called __tuples_for_each to match the convention above where for_each does not return, but apply does return?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Yes, this makes sense

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Done

Copy link
Copy Markdown
Contributor

@danhoeflinger danhoeflinger left a comment

Choose a reason for hiding this comment

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

yeah, overall, I dont have very strong opinions about it but I think its a bit of an improvement, especially if we rename the non-returning tuples_apply to tuples_for_each

Base automatically changed from dev/mdvorski/zip_view to main March 17, 2026 21:04
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR prototypes new internal tuple utilities (__tuple_for_each, __tuple_apply) and refactors zip_view to use them for iterator construction, dereference, increment/decrement, and size/end computations.

Changes:

  • Introduces __tuple_for_each* and __tuple_apply* helpers for operating on tuple elements.
  • Refactors zip_view iterator operators and begin/end/size to use the new helpers.
  • Renames several local “adapter” lambdas to more specific names (__make_iterator, __make_sentinel, etc.).

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@MikeDvorskiy
Copy link
Copy Markdown
Contributor

yeah, overall, I dont have very strong opinions about it but I think its a bit of an improvement, especially if we rename the non-returning tuples_apply to tuples_for_each

lets ask Copilot what name is more suitable in given context :-)

Because, I think the question has is a subjective view. F.e. I dont see "language semantic difference" between apply_to_tuple and tuple_for_each (BTW, rather - for_each_tuple is better).

The main sense - "to apply some lambda/callable object to each component of tuple", right?

So,

  1. apply_to_tuple = to apply some lambda/callable object to each component of tuple. (Because we know that tuple is white box type and has the components, nothing more)
  2. for_each_tuple = to apply (to make for_each) some lambda/callable object to each component of tuple.

1 and 2 are absolutely the same, IMHO.

If you point on "return/no return" - we can improve a little bit the name with return - apply_to_tuple_and_return, but it is too long)...

@kboyarinov
Copy link
Copy Markdown
Contributor Author

Because, I think the question has is a subjective view. F.e. I dont see "language semantic difference" between apply_to_tuple and tuple_for_each (BTW, rather - for_each_tuple is better).

__for_each_tuple literally means "for each tuple in a set of tuples", not "for each element in a tuple".

  1. apply_to_tuple = to apply some lambda/callable object to each component of tuple. (Because we know that tuple is white box type and has the components, nothing more)
  2. for_each_tuple = to apply (to make for_each) some lambda/callable object to each component of tuple.

1 and 2 are absolutely the same, IMHO.

I think there is a meaningful semantic difference between them:

  • apply_to_tuple (like std::tuple)applies a callable to the **entire tuple** once. In other words, the callable receives all tuple elements at the same time. For example, fortuple<int, float>the callable should accept two arguments:intandfloat`.
  • tuple_for_each applies a callable to each element in a tuple individually. The callable is invoked N times, where N is the tuple size. For tuple<int, float>, the callable should accept one (generic) argument that can be either int or float.

In my opinion, that's a substantial semantic differenct.

If you point on "return/no return" - we can improve a little bit the name with return - apply_to_tuple_and_return, but it is too long)...

My "return/no return" point was mainly about the current merged version: it sometimes forces a stub adaptor lambda that returns something even when it is irrelevant. The goal of this patch is to redesign the internal helpers so they accept only what's necessary, avoiding those unnecessary adaptors.

@kboyarinov kboyarinov marked this pull request as ready for review March 18, 2026 11:49
Comment on lines 88 to 91
__tuple_apply_impl(_F __f, _Tuple& __t, std::index_sequence<_Ip...>)
{
return __tr(__f(std::get<_Ip>(__t))...);
return __f(std::get<_Ip>(__t)...);
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I think this overload is confusing. It names the "adaptor" function applied to all elements of the tuple as __f which is the name used in the nearby context for the function applied to each element of the tuple. It also only serves one caller (creation of zip_iterator). Either we should just pass the identity in as the per element function and get rid of this overload, or it should be named better to differentiate it from the rest of the context.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

In fact, this function is a direct analogue of std::apply. I agree that renaming _F to _Adaptor makes sense to align with the second overload.
We could also use a single __tuple_apply_impl with two functions and pass an identity lambda from __tuple_apply, if that makes the intent clearer from your point of view.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Renamed _F to _Adaptor and reused another overload with identity lambda in __tuple_apply with 2 arguments

@kboyarinov
Copy link
Copy Markdown
Contributor Author

@danhoeflinger @MikeDvorskiy
Should we land or discard this?:)

@danhoeflinger
Copy link
Copy Markdown
Contributor

@kboyarinov I havent re-reviewed this but I do think it is an improvement. now that we are past the release, perhaps we can run a full CI on this. If it comes back clean then I would still be in favor of it.

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