Title
std::ranges::fold_left_first_with_iter should be more ADL-proof
Status
new
Section
[alg.fold]
Submitter
Jiang An

Created on 2023-08-10.00:00:00 last changed 8 months ago

Messages

Date: 2023-11-03.18:08:28

Proposed resolution:

This wording is relative to N4950.

  1. Modify [alg.fold] as indicated:

    template<input_iterator I, sentinel_for<I> S,
             indirectly-binary-left-foldable<iter_value_t<I>, I> F>
      requires constructible_from<iter_value_t<I>, iter_reference_t<I>>
      constexpr see below ranges::fold_left_first_with_iter(I first, S last, F f);
    template<input_range R, indirectly-binary-left-foldable<range_value_t<R>, iterator_t<R>> F>
      requires constructible_from<range_value_t<R>, range_reference_t<R>>
      constexpr see below ranges::fold_left_first_with_iter(R&& r, F f);
    

    -9- Let U be

    decltype(ranges::fold_left(std::move(first), last, iter_value_t<I>(*first), f))
    

    -10- Effects: Equivalent to:

    if (first == last)
      return {std::move(first), optional<U>()};
    optional<U> init(in_place, *first);
    for (++first; first != last; ++first)
      *initinit.operator*() = invoke(f, std::move(*initinit.operator*()), *first);
    return {std::move(first), std::move(init)};
    
Date: 2023-11-15.00:00:00

[ 2023-11-03; Reflector poll ]

Many votes for NAD. "Yuck, can we just use .value() instead?" "The example is not good motivation, but we should ADL-proof to avoid attempting to complete incomplete associated classes."

Date: 2023-08-10.00:00:00

The following program is currently ill-formed, because [alg.fold]/10 requires evaluating *init, where init is an object of an optional specialization, which triggers ADL and finds unwanted overloads.

#include <algorithm>
#include <optional>

namespace myns {
  struct Foo {};
  
  void operator*(std::optional<Foo>&);
  void operator*(const std::optional<Foo>&);
}

int main()
{
  myns::Foo x[1]{};
  std::ranges::fold_left_first_with_iter(x, []<class T>(T lhs, T) { return lhs; });
}

I think only the member operator* overload is intendedly used.

History
Date User Action Args
2023-11-03 18:08:28adminsetmessages: + msg13802
2023-08-12 14:10:27adminsetmessages: + msg13708
2023-08-10 00:00:00admincreate