【发布时间】:2019-11-10 01:47:57
【问题描述】:
我编写了一个类似迭代器的类,但由于某种原因,它没有通过 Range v3 中定义的 Readable 概念。我不知道为什么,我想看看我到底需要怎么做 修改语法(和语义)以实现概念。
根据 Range v3,迭代器可读的最低语法要求是什么?可以写一组必须编译的语句吗? (见下面的例子)
我有一个迭代器 It,我可以用它做一些基本的事情(我称之为“可读”),但它没有通过概念检查:
#include <range/v3/all.hpp>
...
It i; // ok
typename It::value_type val = *i; // ok
typename It::reference ref = *i; // ok
typename It::value_type val2{ref}; // ok
static_assert( ranges::CommonReference<typename It::reference&&, typename It::value_type&>{} ); // ok
static_assert( ranges::Readable<It>{} ); // error: static assertion failed
还有哪些涉及i 的构造我可以写出很明显It 不可读? 换句话说,什么泛型代码只能编译且仅当迭代器是 Range v3-Readable?
在很多地方,它说“如果它的行为像一个指针,那么它是可读的”,但我找不到我的迭代器有什么问题。当我看到需要编译的代码时,我就能明白哪里出了问题?
我正在尝试调试为什么我的迭代器无法满足概念(因此被范围 v3 函数拒绝)。请注意,It 和 std::vector<bool>::iterator 都可以。
Range v3 中的可读概念代码https://ericniebler.github.io/range-v3/structranges_1_1v3_1_1concepts_1_1_readable.html 类似于https://en.cppreference.com/w/cpp/experimental/ranges/iterator/Readable
(我使用的是 0.5.0 [Fedora30] 版本)
template < class In >
concept bool Readable =
requires {
typename ranges::value_type_t<In>;
typename ranges::reference_t<In>;
typename ranges::rvalue_reference_t<In>;
} &&
CommonReference<ranges::reference_t<In>&&, ranges::value_type_t<In>&> &&
CommonReference<ranges::reference_t<In>&&, ranges::rvalue_reference_t<In>&&> &&
CommonReference<ranges::rvalue_reference_t<In>&&, const ranges::value_type_t<In>&>;
所以看起来迭代器必须(或可以推断)value_t<It>,从It::value_type 中提取,reference_t<It> 从It::reference 中提取。
我不知道rvalue_reference_t 是如何推导出来的,也不知道CommonReference 在语法约束方面的含义。
【问题讨论】:
-
在 static_assert() 中没有引用 It 和 i。
-
@TanveerBadar,已更正。
-
不知道它是否有帮助,但在 zh.cppreference.com/w/cpp/experimental/ranges/iterator/Readable 中有关于可读概念的第二部分 (
ranges::CommonReference) -
@MartinMorterol,这就是我卡住的地方。我不知道
lvalue_reference_t来自哪里以及CommonReference部分在实践中的含义。 -
您可以玩这个玩具示例:godbolt.org/z/yl0YAf,并看到
Readable做对了。如果迭代器不是Readable(例如,不能转换为value_type,在std::find中使用它会产生编译错误。如果您的迭代器确实适用于标准算法但它不能模拟Readable,请发布最小的例子,以便我们进行调查。
标签: c++ c++11 iterator c++-concepts range-v3