3793. Requirements for some algorithms' Size template parameters are unclear

Section: 26.6.5 [alg.foreach], 26.6.15 [alg.search], 26.7.1 [alg.copy], 26.7.6 [alg.fill], 26.7.7 [alg.generate] Status: New Submitter: Jiang An Opened: 2022-10-05 Last modified: 2022-10-12

Priority: 3

View all other issues in [alg.foreach].

View all issues with New status.

Discussion:

Algorithms std::for_each_n, std::search_n, std::copy_n, std::fill_n, and std::generate_n have similar requirements for the Size template parameter in Mandates, requiring Size to be convertible to an integral type.

However, it is currently underspecified to which integral type Size is converted before further operations. There is implementation divergence:

It is also notable that when the conversion from the source type to integral types is sufficiently ambiguous, none of these implementations accepts such a source type.

For example, currently the following program is rejected by all mainstream implementations.

#include <algorithm>
#include <cstdio>

struct BadFrom {
  operator short() const { return 1; }
  operator unsigned short() const { return 1; }
};

int main()
{
  int arr[42]{};
  std::for_each_n(arr, BadFrom{}, [&arr](int i)
  {
    std::printf("%d\n", i);
  });
}

I think libc++'s strategy make the most sense. But is it really intended to support using a floating-point type or a class type as Size?

Daniel:

The conversion from class type was indeed intended, see the original wording for LWG 3213, which was transferred to P1718R2.

See also LWG 3439 for a similar underspecified situation for template parameter Distance and for the underspecified Size template parameter in various uninitialized_*_n and destroy_n algorithms in 26.11.2 [special.mem.concepts].

ranges::destroy_n has the luxury to simply require iter_difference_t<I>.

[2022-10-12; Reflector poll]

Set priority to 3 after reflector poll.

Proposed resolution: