In [alg.unique], the signature of ranges::unique_copy is defined as:
template<input_iterator I, sentinel_for<I> S, weakly_incrementable O, class Proj = identity,
indirect_equivalence_relation<projected<I, Proj>> C = ranges::equal_to>
requires indirectly_copyable<I, O> &&
(forward_iterator<I> ||
(input_iterator<O> && same_as<iter_value_t<I>, iter_value_t<O>>) ||
indirectly_copyable_storable<I, O>)
constexpr ranges::unique_copy_result<I, O>
ranges::unique_copy(I first, S last, O result, C comp = {}, Proj proj = {});
But I found that when I is only an input_iterator and O is only an output_iterator, the following code fails to compile:
std::istringstream str("42 42 42");
std::ranges::unique_copy(
std::istream_iterator<int>(str),
std::istream_iterator<int>(),
std::ostream_iterator<int>(std::cout, " "));
Both gcc and msvc reject it with (godbolt):
error: no type named 'value_type' in 'using type = struct std::indirectly_readable_traits<std::ostream_iterator<int> >' {aka 'struct std::indirectly_readable_traits<std::ostream_iterator<int> >'}
1436 | && same_as<iter_value_t<_Iter>, iter_value_t<_Out>>)
Surprisingly, the error message here does not show constraints not satisfied, it just complains that there is no value_type in indirectly_readable_traits<ostream_iterator<int>> when instantiating same_as<iter_value_t<_Iter>, iter_value_t<_Out>.
Why is the above code ill-formed in C++20?