-
Notifications
You must be signed in to change notification settings - Fork 1.6k
P2374R4: views::cartesian_product
#3561
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
Conversation
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
|
Finished reviewing, pushed changes for all of the issues I found - the most significant being bogus code in |
This comment was marked as resolved.
This comment was marked as resolved.
|
I'm mirroring this to the MSVC-internal repo - please notify me if any further changes are pushed. |
|
I've pushed a conflict-free merge with |
|
Final boss defeated! 🎉 😻 🚀 |
The final boss of C++23's
std::viewsImplemented papers:
Closes #2923.
Drive-by: replace
constevalwith_CONSTEVALinviews::adjacent_transformimplementation.Implementation details (please read while reviewing)
For simplicity:
CPVmeanscartesian_product_viewhere.Implementation of preconditions for
CPV::sizeandCPV::iterator::distance-fromfunctions:Preconditions of both of those functions require us to check if multiplication or addition is possible without overflow (signed or unsigned). Therefore this PR adds two functions for safe multiplication/addition:
bool _Add_with_overflow_check(x, y, &out)- adds two integersxandywithout undefined behaviour, saves the result in&out, and if an overflow occured - returns true.bool _Multiply_with_overflow_check(x, y, &out)- multiplies two integersxandywithout undefined behaviour, saves the result in&out, and if an overflow occured - returns true. It is based onllvm::MulOverflowfunction (I hope this is fine, sinceNOTICE.txtmentions LLVM project).Signatures of both of those functions are based on Clang's intrinsics
__builtin_add_overflowand__builtin_mul_overflow, exceptoutparameter is a reference (not a pointer).Implementation of
iterator::operator+='s preconditions [range.cartesian.iterator]/19:Currently advacing past end is detected only when first range models
ranges::sized_range. It is possible do detect it for any rangeRng, but it would possibly makeoperator+=linear (for the last range):Implementation of recommended practice for
range_size_tandrange_difference_t:This PR adds
_Cartesian_product_optimal_size_typefunction, which tries to find the best unsigned integer type that satisfies recommendation [range.cartesian.view]/8:To do so, I've added
_Compile_time_max_sizevariable, which detects types with max size known at compile time. Currently those types are:[const] span<T, N>, whereNis notdynamic_extent,[const] array<T, N>,sizefunction, likeviews::emptyorviews::single(ranges::tiny-rangeconcept does similar thing),ranges::ref_viewandranges::owning_view.Then
_Cartesian_product_max_size_bit_width<Rng>function uses this variable to find the smallest bit width for integer type that is able to hold max possible size of given range.Then
_Compile_time_max_size<Ranges...>function sums the results of invocation_Cartesian_product_max_size_bit_widthfor each range inRanges. This sum is the minimal bit width of integer type that is able to hold sum or product of max possible sizes of all ranges inRanges...pack.Then we choose our minimal size type:
The
range_size_tof ourCPVis common type of chosen minimal size type andrange_size_ts of underlying ranges.That said, let's look at the benefits of such approach:
The usage of
_Compile_time_max_sizemay be (and should be) expanded (if we decide to use this approach). There are much more ranges with max size known at compile time, likevector<T, allocator<T>>(value returned byallocator<T>::max_sizeis known at compile time).