libstdc++: Implement ranges::cartesian_product_view from P2374R4
commitf471cb71c86c1e7a3dead324142bdf880f00a3da
authorPatrick Palka <ppalka@redhat.com>
Mon, 7 Nov 2022 18:29:30 +0000 (7 13:29 -0500)
committerPatrick Palka <ppalka@redhat.com>
Mon, 7 Nov 2022 18:29:30 +0000 (7 13:29 -0500)
treeae715f3e7969bde217e8a3bfd49cb4ca15d236f9
parent42f42d70c6ab1dea0a9c2c3ed435890156759aef
libstdc++: Implement ranges::cartesian_product_view from P2374R4

This also implements the proposed resolutions of the tentatively ready
LWG issues 3760, 3761 and 3801 for cartesian_product_view.

I'm not sure how/if we should implement the recommended practice of:

  iterator::difference_type should be the smallest signed-integer-like
  type that is sufficiently wide to store the product of the maximum
  sizes of all underlying ranges if such a type exists

because for e.g.

  extern std::vector<int> x, y;
  auto v = views::cartesian_product(x, y);

IIUC it'd mean difference_type should be __int128 (on 64-bit systems),
which seems quite wasteful: in practice the size of any cartesian product
probably won't exceed the precision of say ptrdiff_t, and using anything
larger will just incur unnecessary space/time overhead.  It's also
probably not worth the complexity to use less precision than ptrdiff_t
(when possible) either.  So this patch defines difference_type as

  common_type_t<ptrdiff_t, range_difference_t<_First>, range_difference_t<_Vs>...>

which should mean it's least as large as the difference_type of each
underlying range, and at least as large as ptrdiff_t.  This patch also
adds assertions to catch any overflow that occurs due to this choice of
difference_type.

libstdc++-v3/ChangeLog:

* include/std/ranges (__maybe_const_t): New alias for
__detail::__maybe_const_t.
(__detail::__cartesian_product_is_random_access): Define.
(__detail::__cartesian_product_common_arg): Define.
(__detail::__cartesian_product_is_bidirectional): Define.
(__detail::__cartesian_product_is_common): Define.
(__detail::__cartesian_product_is_sized): Define.
(__detail::__cartesian_is_sized_sentinel): Define.
(__detail::__cartesian_common_arg_end): Define.
(cartesian_product_view): Define.
(cartesian_product_view::_Iterator): Define.
(views::__detail::__can_cartesian_product_view): Define.
(views::_CartesianProduct, views::cartesian_product): Define.
* testsuite/std/ranges/cartesian_product/1.cc: New test.
libstdc++-v3/include/std/ranges
libstdc++-v3/testsuite/std/ranges/cartesian_product/1.cc [new file with mode: 0644]