Title
ranges::generate_random's helper lambda should specify the return type
Status
new
Section
[alg.rand.generate]
Submitter
Hewill Kang

Created on 2024-04-28.00:00:00 last changed 7 days ago

Messages

Date: 2024-05-12.12:22:51

Proposed resolution:

This wording is relative to N4981.

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

    #include <initializer_list>     // see [initializer.list.syn]
    
    namespace std {
      […]
      namespace ranges {
        […]
        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>> &&
                   is_arithmetic_v<invoke_result_t<D&, 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>> &&
                   is_arithmetic_v<invoke_result_t<D&, G&>>
        constexpr O generate_random(O first, S last, G&& g, D&& d);
      }
      […]
    }
    
  2. Modify [alg.rand.generate] as indicated:

    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>> &&
               is_arithmetic_v<invoke_result_t<D&, G&>>
    constexpr borrowed_iterator_t<R> ranges::generate_random(R&& r, G&& g, D&& d);
    

    -5- Effects:

    […]
    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>> &&
               is_arithmetic_v<invoke_result_t<D&, G&>>
    constexpr O ranges::generate_random(O first, S last, G&& g, D&& d);
    

    -8- Effects: Equivalent to:

    […]
Date: 2024-05-15.00:00:00

[ 2024-05-12, Hewill Kang provides improved wording ]

Date: 2024-05-12.12:22:51

The non-specialized case of generate_random(r, g, d) would call ranges::generate(r, [&d, &g] { return invoke(d, g); }). However, the lambda does not explicitly specify the return type, which leads to a hard error when invoke returns a reference to the object that is not copyable or R is not the output_range for decay_t<invoke_result_t<D&, G&>>.

This wording is relative to N4981.

  1. Modify [alg.rand.generate] as indicated:

    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> ranges::generate_random(R&& r, G&& g, D&& d);
    

    -5- Effects:

    1. (5.1) — […]

    2. (5.2) — […]

    3. (5.3) — Otherwise, calls:

      ranges::generate(std::forward<R>(r), [&d, &g] -> decltype(auto) { return invoke(d, g); });
      

    -6- Returns: ranges::end(r)

    -7- Remarks: The effects of generate_random(r, g, d) shall be equivalent to

    ranges::generate(std::forward<R>(r), [&d, &g] -> decltype(auto) { return invoke(d, g); })
    
History
Date User Action Args
2024-05-12 12:22:51adminsetmessages: + msg14139
2024-05-04 13:08:33adminsetmessages: + msg14093
2024-04-28 00:00:00admincreate