为什么简单的迭代器不可读?
Why is a simple iterator not readable?
此代码无法使用 range-v3
0.10.0
(或 master
)编译。它确实用 range-v3
0.9.1
.
编译
#include "range/v3/all.hpp"
struct double_it {
using value_type = double;
double x;
double& operator*() { return x; }
const double& operator*() const { return x; }
};
static_assert(ranges::readable<double_it>);
哪个版本合适?在 master
中,类型 I
仅当 same_as<iter_reference_t<I const>, iter_reference_t<I>>
时才为 readable
。我不明白为什么 operator*
的 return 类型应该与 operator* const
.
的类型相同
注意:问题提交于 github here。
与 Ranges TS 工作草案相比,这似乎至少是 range-v3
中的一个不一致。
关于为什么 these same_as
predicates were added to to the readable
concept for iterators in range-v3
issue 1449.
的描述非常稀疏
Get the range library compiling with msvc 19.24.28319 with /std:c++17
...
- CPP_concept_fragment(readable_, (I),
+ CPP_concept_fragment(readable_,
+ requires (/*I const i*/) //
+ (
+ // { *i } -> same_as<iter_reference_t<I>>;
+ // { iter_move(i) } -> same_as<iter_rvalue_reference_t<I>>;
+ 0
+ ) &&
+ same_as<iter_reference_t<I const>, iter_reference_t<I>> &&
+ same_as<iter_rvalue_reference_t<I const>, iter_rvalue_reference_t<I>> &&
common_reference_with<iter_reference_t<I> &&, iter_value_t<I> &> &&
common_reference_with<iter_reference_t<I> &&,
iter_rvalue_reference_t<I> &&> &&
common_reference_with<iter_rvalue_reference_t<I> &&, iter_value_t<I> const &>
);
概念实现中的 same_as
谓词似乎旨在实现以下要求:
// { *i } -> same_as<iter_reference_t<I>>;
// { iter_move(i) } -> same_as<iter_rvalue_reference_t<I>>;
甚至在此实施更改之前就存在(如 range/v3/iterator/concepts.hpp
中的注释)。
但是,据我所知,none 这些要求存在于生成先前链接草案的 working draft of [iterators.readable] of Ranges TS (nor in the current HEAD
of ericniebler/stl2 中。
[iterators.readable] Concept Readable
The Readable concept is satisfied by types that are readable by
applying operator* including pointers, smart pointers, and iterators.
template <class In>
concept bool Readable =
requires {
typename value_type_t<In>;
typename reference_t<In>;
typename rvalue_reference_t<In>;
} &&
CommonReference<reference_t<In>&&, value_type_t<In>&> &&
CommonReference<reference_t<In>&&, rvalue_reference_t<In>&&> &&
CommonReference<rvalue_reference_t<In>&&, const value_type_t<In>&>;
report this as an issue 可能是个好主意,至少要弄清楚为什么 range-v3
实现看起来与 Ranges TS 的 [iterators.readable]
不同。
看看 P1878,其中包含了这一后期设计更改的所有基本原理。迭代器代表间接。在 C++ 中,const
-ness 很浅,这意味着它不遵循间接寻址。无论您取消引用 int*
还是 int*const
,您得到的结果都是相同的:int&
。顶级 const
不——也不应该——重要。迭代器和指针一样。他们必须这样做,因为指针是迭代器概念的有效模型。
为了使这种区别更加明确,在 C++20 中,readable
概念称为 indirectly_readable
。
TL;DR:不要让迭代器的引用类型依赖于迭代器本身的 const
-ness。
此代码无法使用 range-v3
0.10.0
(或 master
)编译。它确实用 range-v3
0.9.1
.
#include "range/v3/all.hpp"
struct double_it {
using value_type = double;
double x;
double& operator*() { return x; }
const double& operator*() const { return x; }
};
static_assert(ranges::readable<double_it>);
哪个版本合适?在 master
中,类型 I
仅当 same_as<iter_reference_t<I const>, iter_reference_t<I>>
时才为 readable
。我不明白为什么 operator*
的 return 类型应该与 operator* const
.
注意:问题提交于 github here。
与 Ranges TS 工作草案相比,这似乎至少是 range-v3
中的一个不一致。
关于为什么 these same_as
predicates were added to to the readable
concept for iterators in range-v3
issue 1449.
Get the range library compiling with msvc 19.24.28319 with /std:c++17
...
- CPP_concept_fragment(readable_, (I), + CPP_concept_fragment(readable_, + requires (/*I const i*/) // + ( + // { *i } -> same_as<iter_reference_t<I>>; + // { iter_move(i) } -> same_as<iter_rvalue_reference_t<I>>; + 0 + ) && + same_as<iter_reference_t<I const>, iter_reference_t<I>> && + same_as<iter_rvalue_reference_t<I const>, iter_rvalue_reference_t<I>> && common_reference_with<iter_reference_t<I> &&, iter_value_t<I> &> && common_reference_with<iter_reference_t<I> &&, iter_rvalue_reference_t<I> &&> && common_reference_with<iter_rvalue_reference_t<I> &&, iter_value_t<I> const &> );
概念实现中的 same_as
谓词似乎旨在实现以下要求:
// { *i } -> same_as<iter_reference_t<I>>; // { iter_move(i) } -> same_as<iter_rvalue_reference_t<I>>;
甚至在此实施更改之前就存在(如 range/v3/iterator/concepts.hpp
中的注释)。
但是,据我所知,none 这些要求存在于生成先前链接草案的 working draft of [iterators.readable] of Ranges TS (nor in the current HEAD
of ericniebler/stl2 中。
[iterators.readable] Concept Readable
The Readable concept is satisfied by types that are readable by applying operator* including pointers, smart pointers, and iterators.
template <class In> concept bool Readable = requires { typename value_type_t<In>; typename reference_t<In>; typename rvalue_reference_t<In>; } && CommonReference<reference_t<In>&&, value_type_t<In>&> && CommonReference<reference_t<In>&&, rvalue_reference_t<In>&&> && CommonReference<rvalue_reference_t<In>&&, const value_type_t<In>&>;
report this as an issue 可能是个好主意,至少要弄清楚为什么 range-v3
实现看起来与 Ranges TS 的 [iterators.readable]
不同。
看看 P1878,其中包含了这一后期设计更改的所有基本原理。迭代器代表间接。在 C++ 中,const
-ness 很浅,这意味着它不遵循间接寻址。无论您取消引用 int*
还是 int*const
,您得到的结果都是相同的:int&
。顶级 const
不——也不应该——重要。迭代器和指针一样。他们必须这样做,因为指针是迭代器概念的有效模型。
为了使这种区别更加明确,在 C++20 中,readable
概念称为 indirectly_readable
。
TL;DR:不要让迭代器的引用类型依赖于迭代器本身的 const
-ness。