diff --git a/stl/inc/ranges b/stl/inc/ranges index 76f11b526b..fe82e88999 100644 --- a/stl/inc/ranges +++ b/stl/inc/ranges @@ -38,6 +38,9 @@ namespace ranges { template inline constexpr bool _Is_initializer_list = _Is_specialization_v, initializer_list>; + template // _Require_constant is a valid template-id iff E is a constant expression of structural type + struct _Require_constant; + #if _HAS_CXX23 _EXPORT_STD template using const_iterator_t = const_iterator>; @@ -47,6 +50,34 @@ namespace ranges { _EXPORT_STD template using range_const_reference_t = iter_const_reference_t>; + + template + inline constexpr auto _Compile_time_max_size = + (numeric_limits<_Make_unsigned_like_t>>::max)(); + + template + inline constexpr auto _Compile_time_max_size<_Ty> = (numeric_limits>::max)(); + + template + requires requires { typename _Require_constant<_Ty::size()>; } + inline constexpr auto _Compile_time_max_size<_Ty> = _Ty::size(); + + template + inline constexpr auto _Compile_time_max_size<_Ty[_Size]> = _Size; + + template + inline constexpr auto _Compile_time_max_size> = _Size; + + template + inline constexpr auto _Compile_time_max_size> = _Size; + + template + requires (_Extent != dynamic_extent) + inline constexpr auto _Compile_time_max_size> = _Extent; + + template + requires (_Extent != dynamic_extent) + inline constexpr auto _Compile_time_max_size> = _Extent; #endif // _HAS_CXX23 // clang-format off @@ -1828,6 +1859,14 @@ namespace ranges { template inline constexpr bool enable_borrowed_range> = true; +#if _HAS_CXX23 + template + inline constexpr auto _Compile_time_max_size> = _Compile_time_max_size<_Rng>; + + template + inline constexpr auto _Compile_time_max_size> = _Compile_time_max_size<_Rng>; +#endif // _HAS_CXX23 + _EXPORT_STD template requires (movable<_Rng> && !_Is_initializer_list<_Rng>) class owning_view : public view_interface> { @@ -1915,6 +1954,14 @@ namespace ranges { template inline constexpr bool enable_borrowed_range> = enable_borrowed_range<_Rng>; +#if _HAS_CXX23 + template + inline constexpr auto _Compile_time_max_size> = _Compile_time_max_size<_Rng>; + + template + inline constexpr auto _Compile_time_max_size> = _Compile_time_max_size; +#endif // _HAS_CXX23 + namespace views { template concept _Can_ref_view = requires(_Rng&& __r) { ref_view{static_cast<_Rng&&>(__r)}; }; @@ -2050,6 +2097,14 @@ namespace ranges { template inline constexpr bool enable_borrowed_range> = enable_borrowed_range<_Rng>; +#if _HAS_CXX23 + template + inline constexpr auto _Compile_time_max_size> = _Compile_time_max_size<_Rng>; + + template + inline constexpr auto _Compile_time_max_size> = _Compile_time_max_size; +#endif // _HAS_CXX23 + namespace views { template concept _Can_as_rvalue = requires(_Rng&& __r) { as_rvalue_view{static_cast<_Rng&&>(__r)}; }; @@ -2327,6 +2382,11 @@ namespace ranges { template filter_view(_Rng&&, _Pr) -> filter_view, _Pr>; +#if _HAS_CXX23 + template + inline constexpr auto _Compile_time_max_size> = _Compile_time_max_size<_Rng>; +#endif // _HAS_CXX23 + namespace views { struct _Filter_fn { // clang-format off @@ -2757,6 +2817,14 @@ namespace ranges { template transform_view(_Rng&&, _Fn) -> transform_view, _Fn>; +#if _HAS_CXX23 + template + inline constexpr auto _Compile_time_max_size> = _Compile_time_max_size<_Rng>; + + template + inline constexpr auto _Compile_time_max_size> = _Compile_time_max_size; +#endif // _HAS_CXX23 + namespace views { struct _Transform_fn { // clang-format off @@ -2970,6 +3038,14 @@ namespace ranges { template inline constexpr bool enable_borrowed_range> = enable_borrowed_range<_Rng>; +#if _HAS_CXX23 + template + inline constexpr auto _Compile_time_max_size> = _Compile_time_max_size<_Rng>; + + template + inline constexpr auto _Compile_time_max_size> = _Compile_time_max_size; +#endif // _HAS_CXX23 + namespace views { template concept _Random_sized_range = random_access_range<_Rng> && sized_range<_Rng>; @@ -3211,6 +3287,14 @@ namespace ranges { template take_while_view(_Rng&&, _Pr) -> take_while_view, _Pr>; +#if _HAS_CXX23 + template + inline constexpr auto _Compile_time_max_size> = _Compile_time_max_size<_Rng>; + + template + inline constexpr auto _Compile_time_max_size> = _Compile_time_max_size; +#endif // _HAS_CXX23 + namespace views { struct _Take_while_fn { template @@ -3360,6 +3444,14 @@ namespace ranges { template inline constexpr bool enable_borrowed_range> = enable_borrowed_range<_Rng>; +#if _HAS_CXX23 + template + inline constexpr auto _Compile_time_max_size> = _Compile_time_max_size<_Rng>; + + template + inline constexpr auto _Compile_time_max_size> = _Compile_time_max_size; +#endif // _HAS_CXX23 + namespace views { class _Drop_fn { private: @@ -3525,6 +3617,11 @@ namespace ranges { template inline constexpr bool enable_borrowed_range> = enable_borrowed_range<_Rng>; +#if _HAS_CXX23 + template + inline constexpr auto _Compile_time_max_size> = _Compile_time_max_size<_Rng>; +#endif // _HAS_CXX23 + namespace views { struct _Drop_while_fn { template @@ -3940,6 +4037,30 @@ namespace ranges { template explicit join_view(_Rng&&) -> join_view>; +#if _HAS_CXX23 + template + _NODISCARD consteval auto _Join_view_compile_time_max_size() { + using _Inner = remove_reference_t>; + using _Size_type = + common_type_t), decltype(_Compile_time_max_size<_Inner>)>; + _Size_type _Result{}; + const bool _Overflow = _Mul_overflow(static_cast<_Size_type>(_Compile_time_max_size<_Rng>), + static_cast<_Size_type>(_Compile_time_max_size<_Inner>), _Result); + if (_Overflow) { + return (numeric_limits<_Size_type>::max)(); + } else { + return _Result; + } + } + + template + inline constexpr auto _Compile_time_max_size> = _Join_view_compile_time_max_size<_Rng>(); + + template + inline constexpr auto _Compile_time_max_size> = + _Join_view_compile_time_max_size(); +#endif // _HAS_CXX23 + namespace views { class _Join_fn : public _Pipe::_Base<_Join_fn> { public: @@ -4447,6 +4568,37 @@ namespace ranges { join_with_view(_Rng&&, range_value_t>) -> join_with_view, single_view>>>; +#if _HAS_CXX23 + template + _NODISCARD consteval auto _Join_with_view_compile_time_max_size() { + using _Inner = remove_reference_t>; + using _Size_type = common_type_t), + decltype(_Compile_time_max_size<_Inner>), decltype(_Compile_time_max_size<_Pat>)>; + _Size_type _Joined_max_size{}; + _Size_type _Pattern_max_size{}; + _Size_type _Result{}; + const bool _Overflow = + _Mul_overflow(static_cast<_Size_type>(_Compile_time_max_size<_Rng>), + static_cast<_Size_type>(_Compile_time_max_size<_Inner>), _Joined_max_size) + || _Mul_overflow((_STD max)(static_cast<_Size_type>(_Compile_time_max_size<_Rng>), _Size_type{1}) - 1, + static_cast<_Size_type>(_Compile_time_max_size<_Pat>), _Pattern_max_size) + || _Add_overflow(_Joined_max_size, _Pattern_max_size, _Result); + if (_Overflow) { + return (numeric_limits<_Size_type>::max)(); + } else { + return _Result; + } + } + + template + inline constexpr auto _Compile_time_max_size> = + _Join_with_view_compile_time_max_size<_Rng, _Pat>(); + + template + inline constexpr auto _Compile_time_max_size> = + _Join_with_view_compile_time_max_size(); +#endif // _HAS_CXX23 + namespace views { struct _Join_with_fn { // clang-format off @@ -4471,9 +4623,6 @@ namespace ranges { } // namespace views #endif // _HAS_CXX23 - template // _Require_constant is a valid template-id iff E is a constant expression of structural type - struct _Require_constant; - // clang-format off template concept _Tiny_range = sized_range<_Ty> @@ -4868,6 +5017,15 @@ namespace ranges { lazy_split_view(_Rng&&, range_value_t<_Rng>) -> lazy_split_view, single_view>>; +#if _HAS_CXX23 + template + inline constexpr auto _Compile_time_max_size> = _Compile_time_max_size<_Rng>; + + template + inline constexpr auto _Compile_time_max_size> = + _Compile_time_max_size; +#endif // _HAS_CXX23 + namespace views { struct _Lazy_split_fn { // clang-format off @@ -5064,6 +5222,11 @@ namespace ranges { template split_view(_Rng&&, range_value_t<_Rng>) -> split_view, single_view>>; +#if _HAS_CXX23 + template + inline constexpr auto _Compile_time_max_size> = _Compile_time_max_size<_Rng>; +#endif // _HAS_CXX23 + namespace views { struct _Split_fn { // clang-format off @@ -5214,6 +5377,14 @@ namespace ranges { template inline constexpr bool enable_borrowed_range> = enable_borrowed_range<_Rng>; +#if _HAS_CXX23 + template + inline constexpr auto _Compile_time_max_size> = _Compile_time_max_size<_Rng>; + + template + inline constexpr auto _Compile_time_max_size> = _Compile_time_max_size; +#endif // _HAS_CXX23 + namespace views { class _Common_fn : public _Pipe::_Base<_Common_fn> { private: @@ -5333,6 +5504,14 @@ namespace ranges { template inline constexpr bool enable_borrowed_range> = enable_borrowed_range<_Rng>; +#if _HAS_CXX23 + template + inline constexpr auto _Compile_time_max_size> = _Compile_time_max_size<_Rng>; + + template + inline constexpr auto _Compile_time_max_size> = _Compile_time_max_size; +#endif // _HAS_CXX23 + namespace views { template concept _Can_extract_base = requires(_Rng&& __r) { static_cast<_Rng&&>(__r).base(); }; @@ -5470,6 +5649,14 @@ namespace ranges { template inline constexpr bool enable_borrowed_range> = enable_borrowed_range<_Rng>; +#if _HAS_CXX23 + template + inline constexpr auto _Compile_time_max_size> = _Compile_time_max_size<_Rng>; + + template + inline constexpr auto _Compile_time_max_size> = _Compile_time_max_size; +#endif // _HAS_CXX23 + namespace views { template concept _Can_as_const = requires(_Rng&& __r) { as_const_view{static_cast<_Rng&&>(__r)}; }; @@ -5940,6 +6127,15 @@ namespace ranges { template inline constexpr bool enable_borrowed_range> = enable_borrowed_range<_Rng>; +#if _HAS_CXX23 + template + inline constexpr auto _Compile_time_max_size> = _Compile_time_max_size<_Rng>; + + template + inline constexpr auto _Compile_time_max_size> = + _Compile_time_max_size; +#endif // _HAS_CXX23 + _EXPORT_STD template using keys_view = elements_view<_Rng, 0>; _EXPORT_STD template @@ -6282,6 +6478,14 @@ namespace ranges { template inline constexpr bool enable_borrowed_range> = enable_borrowed_range<_Rng>; +#if _HAS_CXX23 + template + inline constexpr auto _Compile_time_max_size> = _Compile_time_max_size<_Rng>; + + template + inline constexpr auto _Compile_time_max_size> = _Compile_time_max_size; +#endif // _HAS_CXX23 + namespace views { class _Enumerate_fn : public _Pipe::_Base<_Enumerate_fn> { public: @@ -6876,6 +7080,15 @@ namespace ranges { template inline constexpr bool enable_borrowed_range> = enable_borrowed_range<_Vw> && forward_range<_Vw>; +#if _HAS_CXX23 + template + inline constexpr auto _Compile_time_max_size> = _Compile_time_max_size<_Rng>; + + template + requires forward_range<_Rng> + inline constexpr auto _Compile_time_max_size> = _Compile_time_max_size; +#endif // _HAS_CXX23 + namespace views { struct _Chunk_fn { // clang-format off @@ -7268,6 +7481,14 @@ namespace ranges { template inline constexpr bool enable_borrowed_range> = enable_borrowed_range<_Vw>; +#if _HAS_CXX23 + template + inline constexpr auto _Compile_time_max_size> = _Compile_time_max_size<_Rng>; + + template + inline constexpr auto _Compile_time_max_size> = _Compile_time_max_size; +#endif // _HAS_CXX23 + namespace views { struct _Slide_fn { // clang-format off @@ -7467,6 +7688,11 @@ namespace ranges { template chunk_by_view(_Rng&&, _Pr) -> chunk_by_view, _Pr>; +#if _HAS_CXX23 + template + inline constexpr auto _Compile_time_max_size> = _Compile_time_max_size<_Rng>; +#endif // _HAS_CXX23 + namespace views { struct _Chunk_by_fn { // clang-format off @@ -7856,6 +8082,14 @@ namespace ranges { template inline constexpr bool enable_borrowed_range> = enable_borrowed_range<_Vw>; +#if _HAS_CXX23 + template + inline constexpr auto _Compile_time_max_size> = _Compile_time_max_size<_Rng>; + + template + inline constexpr auto _Compile_time_max_size> = _Compile_time_max_size; +#endif // _HAS_CXX23 + namespace views { struct _Stride_fn { // clang-format off @@ -8349,6 +8583,21 @@ namespace ranges { template inline constexpr bool enable_borrowed_range> = (enable_borrowed_range<_ViewTypes> && ...); +#if _HAS_CXX23 + template + _NODISCARD consteval auto _Zip_view_compile_time_max_size() { + using _Size_type = common_type_t)...>; + return (_STD min)({static_cast<_Size_type>(_Compile_time_max_size<_Rngs>)...}); + } + + template + inline constexpr auto _Compile_time_max_size> = _Zip_view_compile_time_max_size<_Rngs...>(); + + template + inline constexpr auto _Compile_time_max_size> = + _Zip_view_compile_time_max_size(); +#endif // _HAS_CXX23 + namespace views { struct _Zip_fn { private: @@ -8687,6 +8936,16 @@ namespace ranges { template zip_transform_view(_Func, _Ranges&&...) -> zip_transform_view<_Func, views::all_t<_Ranges>...>; +#if _HAS_CXX23 + template + inline constexpr auto _Compile_time_max_size> = + _Compile_time_max_size>; + + template + inline constexpr auto _Compile_time_max_size> = + _Compile_time_max_size>; +#endif // _HAS_CXX23 + namespace views { struct _Zip_transform_fn { private: @@ -9143,6 +9402,24 @@ namespace ranges { template inline constexpr bool enable_borrowed_range> = enable_borrowed_range<_Rng>; +#if _HAS_CXX23 + template + _NODISCARD consteval auto _Adjacent_view_compile_time_max_size() { + using _Size_type = common_type_t), size_t>; + auto _Size = static_cast<_Size_type>(_Compile_time_max_size<_Rng>); + _Size -= (_STD min)(_Size, static_cast<_Size_type>(_Nx - 1)); + return static_cast<_Size_type>(_Size); + } + + template + inline constexpr auto _Compile_time_max_size> = + _Adjacent_view_compile_time_max_size<_Rng, _Nx>(); + + template + inline constexpr auto _Compile_time_max_size> = + _Adjacent_view_compile_time_max_size(); +#endif // _HAS_CXX23 + namespace views { template class _Adjacent_fn : public _Pipe::_Base<_Adjacent_fn<_Nx>> { @@ -9478,6 +9755,16 @@ namespace ranges { } }; +#if _HAS_CXX23 + template + inline constexpr auto _Compile_time_max_size> = + _Compile_time_max_size>; + + template + inline constexpr auto _Compile_time_max_size> = + _Compile_time_max_size>; +#endif // _HAS_CXX23 + namespace views { template class _Adjacent_transform_fn { @@ -9551,69 +9838,28 @@ namespace ranges { } } - template - inline constexpr auto _Compile_time_max_size = (numeric_limits>::max)(); - - template - concept _Constant_sized_range = - sized_range<_Ty> && requires { typename _Require_constant::size()>; }; - - template <_Constant_sized_range _Ty> - inline constexpr auto _Compile_time_max_size<_Ty> = remove_reference_t<_Ty>::size(); - - template - inline constexpr auto _Compile_time_max_size> = _Size; - - template - inline constexpr auto _Compile_time_max_size> = _Size; - - template - requires (_Extent != dynamic_extent) - inline constexpr auto _Compile_time_max_size> = _Extent; - - template - requires (_Extent != dynamic_extent) - inline constexpr auto _Compile_time_max_size> = _Extent; - - template - inline constexpr auto _Compile_time_max_size> = _Compile_time_max_size<_Ty>; - - template - requires sized_range - inline constexpr auto _Compile_time_max_size> = _Compile_time_max_size; - - template - inline constexpr auto _Compile_time_max_size> = _Compile_time_max_size<_Ty>; - - template - requires sized_range - inline constexpr auto _Compile_time_max_size> = _Compile_time_max_size; - - template - _NODISCARD consteval int _Cartesian_product_max_size_bit_width() noexcept { - if constexpr (sized_range<_Rng>) { - if constexpr (requires(range_size_t<_Rng> _Val) { _STD bit_width(_Val); }) { - return _STD bit_width(_Compile_time_max_size<_Rng>); - } else { - return numeric_limits>::digits; - } + template + _NODISCARD consteval int _Cartesian_product_max_size_bit_width() { + using _Size_type = decltype(_Compile_time_max_size<_Rng>); + if constexpr (requires(_Size_type _Val) { _STD bit_width(_Val); }) { + return _STD bit_width(_Compile_time_max_size<_Rng>); } else { - return numeric_limits<_Make_unsigned_like_t>>::digits; + return numeric_limits<_Size_type>::digits; } } - template + template + requires (sizeof...(_Rngs) > 0) _NODISCARD consteval auto _Cartesian_product_optimal_size_type() noexcept { - constexpr int _Optimal_size_type_bit_width = - (_Cartesian_product_max_size_bit_width<_First>() + ... + _Cartesian_product_max_size_bit_width<_Rest>()); + constexpr int _Optimal_size_type_bit_width = (_Cartesian_product_max_size_bit_width<_Rngs>() + ...); if constexpr (_Optimal_size_type_bit_width <= 8) { - return uint_least8_t{}; + return uint8_t{}; } else if constexpr (_Optimal_size_type_bit_width <= 16) { - return uint_least16_t{}; + return uint16_t{}; } else if constexpr (_Optimal_size_type_bit_width <= 32) { - return uint_least32_t{}; + return uint32_t{}; } else if constexpr (_Optimal_size_type_bit_width <= 64) { - return uint_least64_t{}; + return uint64_t{}; } else { return _Unsigned128{}; } @@ -10037,6 +10283,30 @@ namespace ranges { template cartesian_product_view(_Rngs&&...) -> cartesian_product_view...>; +#if _HAS_CXX23 + template + _NODISCARD consteval auto _Cartesian_product_view_compile_time_max_size() { + using _Size_type = common_type_t()), + decltype(_Compile_time_max_size<_Rngs>)...>; + _Size_type _Result{1}; + const bool _Overflow = + (_Mul_overflow(static_cast<_Size_type>(_Compile_time_max_size<_Rngs>), _Result, _Result) || ...); + if (_Overflow) { + return (numeric_limits<_Size_type>::max)(); + } else { + return _Result; + } + } + + template + inline constexpr auto _Compile_time_max_size> = + _Cartesian_product_view_compile_time_max_size<_Rngs...>(); + + template + inline constexpr auto _Compile_time_max_size> = + _Cartesian_product_view_compile_time_max_size(); +#endif // _HAS_CXX23 + namespace views { class _Cartesian_product_fn { public: diff --git a/tests/std/test.lst b/tests/std/test.lst index 3059eef140..9482c7ea7a 100644 --- a/tests/std/test.lst +++ b/tests/std/test.lst @@ -591,6 +591,7 @@ tests\P2322R6_ranges_alg_fold tests\P2374R4_checked_arithmetic_operations tests\P2374R4_views_cartesian_product tests\P2374R4_views_cartesian_product_death +tests\P2374R4_views_cartesian_product_recommended_practices tests\P2387R3_bind_back tests\P2387R3_pipe_support_for_user_defined_range_adaptors tests\P2401R0_conditional_noexcept_for_exchange diff --git a/tests/std/tests/P2374R4_views_cartesian_product/test.cpp b/tests/std/tests/P2374R4_views_cartesian_product/test.cpp index eedcde49ee..b38606f23d 100644 --- a/tests/std/tests/P2374R4_views_cartesian_product/test.cpp +++ b/tests/std/tests/P2374R4_views_cartesian_product/test.cpp @@ -922,57 +922,6 @@ using move_only_view = test::range}, test::ProxyRef{!derived_from}, test::CanView::yes, test::Copyability::move_only>; -namespace check_recommended_practice_implementation { // MSVC STL specific behavior - using ranges::cartesian_product_view, ranges::empty_view, ranges::single_view, views::all_t, ranges::range_size_t, - ranges::range_difference_t, ranges::ref_view, ranges::owning_view; - using Arr = array; - using Vec = vector; - using Span = span; - - // Computing product for such small array does not require big range_size_t - STATIC_ASSERT(sizeof(range_size_t>>) <= sizeof(size_t)); - STATIC_ASSERT(sizeof(range_size_t, all_t>>) <= sizeof(size_t)); - STATIC_ASSERT(sizeof(range_size_t, all_t, all_t>>) <= sizeof(size_t)); - - // Same thing with range_difference_t - STATIC_ASSERT(sizeof(range_difference_t>>) <= sizeof(ptrdiff_t)); - STATIC_ASSERT(sizeof(range_difference_t, all_t>>) <= sizeof(ptrdiff_t)); - STATIC_ASSERT( - sizeof(range_difference_t, all_t, all_t>>) <= sizeof(ptrdiff_t)); - - // Computing product for such small span does not require big range_size_t - STATIC_ASSERT(sizeof(range_size_t>>) <= sizeof(size_t)); - STATIC_ASSERT(sizeof(range_size_t, all_t>>) <= sizeof(size_t)); - STATIC_ASSERT( - sizeof(range_size_t, all_t, all_t>>) <= sizeof(size_t)); - - // Same thing with range_difference_t - STATIC_ASSERT(sizeof(range_difference_t>>) <= sizeof(ptrdiff_t)); - STATIC_ASSERT(sizeof(range_difference_t, all_t>>) <= sizeof(ptrdiff_t)); - STATIC_ASSERT( - sizeof(range_difference_t, all_t, all_t>>) <= sizeof(ptrdiff_t)); - - // Check 'single_view' and 'empty_view' - STATIC_ASSERT(sizeof(range_size_t, single_view>>) <= sizeof(size_t)); - STATIC_ASSERT( - sizeof(range_difference_t, single_view>>) <= sizeof(ptrdiff_t)); - - // Check 'ref_view<(const) V>' and 'owning_view' - STATIC_ASSERT(sizeof(range_size_t, ref_view, owning_view>>) - <= sizeof(size_t)); - STATIC_ASSERT( - sizeof(range_difference_t, ref_view, owning_view>>) - <= sizeof(ptrdiff_t)); - - // One vector should not use big integer-class type... - STATIC_ASSERT(sizeof(range_size_t>>) <= sizeof(size_t)); - STATIC_ASSERT(sizeof(range_difference_t>>) <= sizeof(ptrdiff_t)); - - // ... but two vectors will - STATIC_ASSERT(sizeof(range_size_t, all_t>>) > sizeof(size_t)); - STATIC_ASSERT(sizeof(range_difference_t, all_t>>) > sizeof(ptrdiff_t)); -} // namespace check_recommended_practice_implementation - // GH-3733: cartesian_product_view would incorrectly reject a call to size() claiming that big*big*big*0 is not // representable as range_size_t because big*big*big is not. constexpr void test_gh_3733() { diff --git a/tests/std/tests/P2374R4_views_cartesian_product_recommended_practices/env.lst b/tests/std/tests/P2374R4_views_cartesian_product_recommended_practices/env.lst new file mode 100644 index 0000000000..8ac7033b20 --- /dev/null +++ b/tests/std/tests/P2374R4_views_cartesian_product_recommended_practices/env.lst @@ -0,0 +1,4 @@ +# Copyright (c) Microsoft Corporation. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +RUNALL_INCLUDE ..\strict_concepts_latest_matrix.lst diff --git a/tests/std/tests/P2374R4_views_cartesian_product_recommended_practices/test.compile.pass.cpp b/tests/std/tests/P2374R4_views_cartesian_product_recommended_practices/test.compile.pass.cpp new file mode 100644 index 0000000000..42f982da64 --- /dev/null +++ b/tests/std/tests/P2374R4_views_cartesian_product_recommended_practices/test.compile.pass.cpp @@ -0,0 +1,497 @@ +// Copyright (c) Microsoft Corporation. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +// Check MSVC-STL internal machinery + +#include +#include +#include +#include +#include +#include +#include + +using namespace std; +using ranges::_Compile_time_max_size, ranges::cartesian_product_view, ranges::sized_range, ranges::range_difference_t, + ranges::range_size_t, views::all_t; + +template +using cpv_size_t = range_size_t>; + +template +using cpv_difference_t = range_difference_t>; + +template +using cpv_const_size_t = range_size_t>; + +template +using cpv_const_difference_t = range_difference_t>; + +#ifdef _WIN64 +constexpr bool is_64_bit = true; +#else // ^^^ 64 bit ^^^ / vvv 32 bit vvv +constexpr bool is_64_bit = false; +#endif // ^^^ 32 bit ^^^ + +constexpr void check_array() { + // Check '_Compile_time_max_size' type trait + static_assert(_Compile_time_max_size == 3); + static_assert(_Compile_time_max_size == 9); + + // Check '_Compile_time_max_size' type trait for const arrays + static_assert(_Compile_time_max_size == 3); + static_assert(_Compile_time_max_size == 9); + + // Computing cartesian product for small arrays does not require big range_size_t + using A1 = all_t; + static_assert(sizeof(cpv_size_t) <= sizeof(size_t)); + static_assert(sizeof(cpv_size_t) <= sizeof(size_t)); + static_assert(sizeof(cpv_size_t) <= sizeof(size_t)); + + // Same thing with range_difference_t + static_assert(sizeof(cpv_difference_t) <= sizeof(ptrdiff_t)); + static_assert(sizeof(cpv_difference_t) <= sizeof(ptrdiff_t)); + static_assert(sizeof(cpv_difference_t) <= sizeof(ptrdiff_t)); + +#ifndef __clang__ // TRANSITION, Clang 17 + // Computing cartesian product for big arrays requires bigger types + using A2 = all_t; + static_assert(sizeof(cpv_size_t) > sizeof(size_t)); + static_assert(sizeof(cpv_difference_t) > sizeof(ptrdiff_t)); +#endif // __clang__ +} + +constexpr void check_std_array() { + // Check '_Compile_time_max_size' type trait + static_assert(_Compile_time_max_size> == 0); + static_assert(_Compile_time_max_size> == 3); + static_assert(_Compile_time_max_size> == 9); + + // Check '_Compile_time_max_size' type trait for const arrays + static_assert(_Compile_time_max_size> == 0); + static_assert(_Compile_time_max_size> == 3); + static_assert(_Compile_time_max_size> == 9); + + // Computing cartesian product for small arrays does not require big range_size_t + using A1 = all_t>; + static_assert(sizeof(cpv_size_t) <= sizeof(size_t)); + static_assert(sizeof(cpv_size_t) <= sizeof(size_t)); + static_assert(sizeof(cpv_size_t) <= sizeof(size_t)); + static_assert(sizeof(cpv_const_size_t) <= sizeof(size_t)); + static_assert(sizeof(cpv_const_size_t) <= sizeof(size_t)); + static_assert(sizeof(cpv_const_size_t) <= sizeof(size_t)); + + // Same thing with range_difference_t + static_assert(sizeof(cpv_difference_t) <= sizeof(ptrdiff_t)); + static_assert(sizeof(cpv_difference_t) <= sizeof(ptrdiff_t)); + static_assert(sizeof(cpv_difference_t) <= sizeof(ptrdiff_t)); + static_assert(sizeof(cpv_const_difference_t) <= sizeof(ptrdiff_t)); + static_assert(sizeof(cpv_const_difference_t) <= sizeof(ptrdiff_t)); + static_assert(sizeof(cpv_const_difference_t) <= sizeof(ptrdiff_t)); + + // Computing cartesian product for big arrays requires bigger types + using A2 = all_t&>; + static_assert(sizeof(cpv_size_t) > sizeof(size_t)); + static_assert(sizeof(cpv_difference_t) > sizeof(ptrdiff_t)); + static_assert(sizeof(cpv_const_size_t) > sizeof(size_t)); + static_assert(sizeof(cpv_const_difference_t) > sizeof(ptrdiff_t)); +} + +constexpr void check_span() { + // Check '_Compile_time_max_size' type trait + static_assert(_Compile_time_max_size> == 0); + static_assert(_Compile_time_max_size> == 3); + static_assert(_Compile_time_max_size> == 9); + static_assert(_Compile_time_max_size> == (numeric_limits::size_type>::max)()); + + // Check '_Compile_time_max_size' type trait for const spans + static_assert(_Compile_time_max_size> == 0); + static_assert(_Compile_time_max_size> == 3); + static_assert(_Compile_time_max_size> == 9); + static_assert(_Compile_time_max_size> == (numeric_limits::size_type>::max)()); + + // Computing cartesian product for small spans does not require big range_size_t + using S1 = all_t>; + static_assert(sizeof(cpv_size_t) <= sizeof(size_t)); + static_assert(sizeof(cpv_size_t) <= sizeof(size_t)); + static_assert(sizeof(cpv_size_t) <= sizeof(size_t)); + static_assert(sizeof(cpv_const_size_t) <= sizeof(size_t)); + static_assert(sizeof(cpv_const_size_t) <= sizeof(size_t)); + static_assert(sizeof(cpv_const_size_t) <= sizeof(size_t)); + + // Same thing with range_difference_t + static_assert(sizeof(cpv_difference_t) <= sizeof(ptrdiff_t)); + static_assert(sizeof(cpv_difference_t) <= sizeof(ptrdiff_t)); + static_assert(sizeof(cpv_difference_t) <= sizeof(ptrdiff_t)); + static_assert(sizeof(cpv_const_difference_t) <= sizeof(ptrdiff_t)); + static_assert(sizeof(cpv_const_difference_t) <= sizeof(ptrdiff_t)); + static_assert(sizeof(cpv_const_difference_t) <= sizeof(ptrdiff_t)); + + // Computing cartesian product for big spans requires bigger types + using S2 = span; + static_assert(sizeof(cpv_size_t) > sizeof(size_t)); + static_assert(sizeof(cpv_difference_t) > sizeof(ptrdiff_t)); + static_assert(sizeof(cpv_const_size_t) > sizeof(size_t)); + static_assert(sizeof(cpv_const_difference_t) > sizeof(ptrdiff_t)); +} + +constexpr void check_empty_view() { + using ranges::empty_view; + + // Check '_Compile_time_max_size' type trait + static_assert(_Compile_time_max_size> == 0); + static_assert(_Compile_time_max_size> == 0); + static_assert(_Compile_time_max_size> == 0); + static_assert(_Compile_time_max_size> == 0); + + using E = empty_view; + static_assert(sizeof(cpv_size_t) <= sizeof(size_t)); + static_assert(sizeof(cpv_difference_t) <= sizeof(ptrdiff_t)); + static_assert(sizeof(cpv_size_t) <= sizeof(size_t)); + static_assert(sizeof(cpv_difference_t) <= sizeof(ptrdiff_t)); + static_assert(sizeof(cpv_const_size_t) <= sizeof(size_t)); + static_assert(sizeof(cpv_const_difference_t) <= sizeof(ptrdiff_t)); + static_assert(sizeof(cpv_const_size_t) <= sizeof(size_t)); + static_assert(sizeof(cpv_const_difference_t) <= sizeof(ptrdiff_t)); +} + +constexpr void check_single_view() { + using ranges::single_view; + + // Check '_Compile_time_max_size' type trait + static_assert(_Compile_time_max_size> == 1); + static_assert(_Compile_time_max_size> == 1); + static_assert(_Compile_time_max_size> == 1); + static_assert(_Compile_time_max_size> == 1); + + using S = single_view; + static_assert(sizeof(cpv_size_t) <= sizeof(size_t)); + static_assert(sizeof(cpv_difference_t) <= sizeof(ptrdiff_t)); + static_assert(sizeof(cpv_size_t) <= sizeof(size_t)); + static_assert(sizeof(cpv_difference_t) <= sizeof(ptrdiff_t)); + static_assert(sizeof(cpv_const_size_t) <= sizeof(size_t)); + static_assert(sizeof(cpv_const_difference_t) <= sizeof(ptrdiff_t)); + static_assert(sizeof(cpv_const_size_t) <= sizeof(size_t)); + static_assert(sizeof(cpv_const_difference_t) <= sizeof(ptrdiff_t)); +} + +enum class CheckConstAdaptor : bool { no, yes }; + +template