This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of NAD status.

4086. ranges::generate_random_n is missing

Section: 26.12.2 [alg.rand.generate] Status: NAD Submitter: Hewill Kang Opened: 2024-04-29 Last modified: 2024-06-24

Priority: Not Prioritized

View other active issues in [alg.rand.generate].

View all other issues in [alg.rand.generate].

View all issues with NAD status.

Discussion:

P1068 introduced ranges::generate_random which has both range and iterator-sentinel pair overloads. However, the _n version never seems to be discussed.

In view of the fact that generate and fill have their corresponding _n siblings, namely generate_n and fill_n, adding generate_random_n does improve consistency and provide a more intuitive and simple way to generate a specified number of random numbers.

[2024-06-24; Reflector poll]

NAD, this is a feature request not a defect. Needs a paper.

[St. Louis 2024-06-24 Status changed: Tentatively NAD → NAD.]

Proposed resolution:

This wording is relative to N4981.

  1. Modify 29.5.2 [rand.synopsis], header <random> synopsis, as indicated:

    #include <initializer_list>     // see 17.10.2 [initializer.list.syn]
    
    namespace std {
      […]
      namespace ranges {
        // 26.12.2 [alg.rand.generate], generate_random
        template<class R, class G>
          requires output_range<R, invoke_result_t<G&>> &&
                   uniform_random_bit_generator<remove_cvref_t<G>>
          constexpr borrowed_iterator_t<R> generate_random(R&& r, G&& g);
    
        template<class G, output_iterator<invoke_result_t<G&>> O, sentinel_for<O> S>
          requires uniform_random_bit_generator<remove_cvref_t<G>>
          constexpr O generate_random(O first, S last, G&& g);
    
        template<class G, output_iterator<invoke_result_t<G&>> O>
          requires uniform_random_bit_generator<remove_cvref_t<G>>
          constexpr O generate_random_n(O first, iter_difference_t<O> n, G&& g);
    
        template<class R, class G, class D>
          requires output_range<R, invoke_result_t<D&, G&>> && invocable<D&, G&> &&
                   uniform_random_bit_generator<remove_cvref_t<G>>
        constexpr borrowed_iterator_t<R> generate_random(R&& r, G&& g, D&& d);
    
        template<class G, class D, output_iterator<invoke_result_t<D&, G&>> O, sentinel_for<O> S>
          requires invocable<D&, G&> && uniform_random_bit_generator<remove_cvref_t<G>>
        constexpr O generate_random(O first, S last, G&& g, D&& d);
    
        template<class G, class D, output_iterator<invoke_result_t<D&, G&>> O>
          requires invocable<D&, G&> && uniform_random_bit_generator<remove_cvref_t<G>>
        constexpr O generate_random_n(O first, iter_difference_t<O> n, G&& g, D&& d);
      }
      […]
    }
    
  2. Modify 26.12.2 [alg.rand.generate] as indicated:

    template<class G, output_iterator<invoke_result_t<G&>> O, sentinel_for<O> S>
      requires uniform_random_bit_generator<remove_cvref_t<G>>
    constexpr O ranges::generate_random(O first, S last, G&& g);
    

    -4- Effects: Equivalent to:

    return generate_random(subrange<O, S>(std::move(first), last), g);
    
    
    template<class G, output_iterator<invoke_result_t<G&>> O>
      requires uniform_random_bit_generator<remove_cvref_t<G>>
    constexpr O ranges::generate_random_n(O first, iter_difference_t<O> n, G&& g);
    

    -?- Effects: Equivalent to:

    return generate_random(counted_iterator(std::move(first), n),
                default_sentinel, g).base();
    
    […]
    template<class G, class D, output_iterator<invoke_result_t<D&, G&>> O, sentinel_for<O> S>
      requires invocable<D&, G&> && uniform_random_bit_generator<remove_cvref_t<G>>
    constexpr O ranges::generate_random(O first, S last, G&& g, D&& d);
    

    -8- Effects: Equivalent to:

    return generate_random(subrange<O, S>(std::move(first), last), g, d);
    
    
    template<class G, class D, output_iterator<invoke_result_t<D&, G&>> O>
      requires invocable<D&, G&> && uniform_random_bit_generator<remove_cvref_t<G>>
    constexpr O ranges::generate_random_n(O first, iter_difference_t<O> n, G&& g, D&& d);
    

    -?- Effects: Equivalent to:

    return generate_random(counted_iterator(std::move(first), n),
              default_sentinel, g, d).base();