为什么 ranges::unique_copy 不能与 std::ostream_iterator 一起使用?
Why ranges::unique_copy cannot work with std::ostream_iterator?
在[alg.unique], the signature of ranges::unique_copy
中定义为:
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 = {});
但是我发现当I
只是一个input_iterator
而O
只是一个output_iterator
时,下面的代码无法编译:
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, " "));
gcc 和 msvc 都拒绝它 (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>>)
奇怪的是,这里的报错信息并没有显示constraints not satisfied
,只是在实例化same_as<iter_value_t<_Iter>, iter_value_t<_Out>
时抱怨indirectly_readable_traits<ostream_iterator<int>>
中没有value_type
。
为什么上面的代码在 C++20 中格式错误?
这是两个实现中的错误。两者都包含相当于
if constexpr (input_iterator<O> && same_as<iter_value_t<I>, iter_value_t<O>>)
在约束中这很好,因为约束满足度是通过短路逐步检查的(并且在任何情况下替换失败只会导致约束评估为 false
),因此如果 O
是对于输入迭代器,我们不会询问它的(可能不存在的)值类型。在 if constexpr
中没有短路,因此整个表达式被替换为并且当场不正确。
在[alg.unique], the signature of ranges::unique_copy
中定义为:
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 = {});
但是我发现当I
只是一个input_iterator
而O
只是一个output_iterator
时,下面的代码无法编译:
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, " "));
gcc 和 msvc 都拒绝它 (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>>)
奇怪的是,这里的报错信息并没有显示constraints not satisfied
,只是在实例化same_as<iter_value_t<_Iter>, iter_value_t<_Out>
时抱怨indirectly_readable_traits<ostream_iterator<int>>
中没有value_type
。
为什么上面的代码在 C++20 中格式错误?
这是两个实现中的错误。两者都包含相当于
if constexpr (input_iterator<O> && same_as<iter_value_t<I>, iter_value_t<O>>)
在约束中这很好,因为约束满足度是通过短路逐步检查的(并且在任何情况下替换失败只会导致约束评估为 false
),因此如果 O
是对于输入迭代器,我们不会询问它的(可能不存在的)值类型。在 if constexpr
中没有短路,因此整个表达式被替换为并且当场不正确。