-
Notifications
You must be signed in to change notification settings - Fork 1.5k
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
P2374R4: views::cartesian_product
#3561
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::views
Implemented papers:
Closes #2923.
Drive-by: replace
consteval
with_CONSTEVAL
inviews::adjacent_transform
implementation.Implementation details (please read while reviewing)
For simplicity:
CPV
meanscartesian_product_view
here.Implementation of preconditions for
CPV::size
andCPV::iterator::distance-from
functions: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 integersx
andy
without undefined behaviour, saves the result in&out
, and if an overflow occured - returns true.bool _Multiply_with_overflow_check(x, y, &out)
- multiplies two integersx
andy
without undefined behaviour, saves the result in&out
, and if an overflow occured - returns true. It is based onllvm::MulOverflow
function (I hope this is fine, sinceNOTICE.txt
mentions LLVM project).Signatures of both of those functions are based on Clang's intrinsics
__builtin_add_overflow
and__builtin_mul_overflow
, exceptout
parameter 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_t
andrange_difference_t
:This PR adds
_Cartesian_product_optimal_size_type
function, 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_size
variable, which detects types with max size known at compile time. Currently those types are:[const] span<T, N>
, whereN
is notdynamic_extent
,[const] array<T, N>
,size
function, likeviews::empty
orviews::single
(ranges::tiny-range
concept does similar thing),ranges::ref_view
andranges::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_width
for 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_t
of ourCPV
is common type of chosen minimal size type andrange_size_t
s of underlying ranges.That said, let's look at the benefits of such approach:
The usage of
_Compile_time_max_size
may 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_size
is known at compile time).