【问题标题】:How does one implement a container which exposes multiple ranges?如何实现一个暴露多个范围的容器?
【发布时间】:2013-12-22 02:17:36
【问题描述】:

我有一个容器(除其他外)公开了一个字符串缓冲区,以及该字符串缓冲区的大写版本。 (嗯,它不只是大写,但在概念上是相似的)我想让调用者做类似的事情:

container c("Example");
auto const iter = c.begin() + 2;
std::printf("%c\n", iter->get_source()); // Prints a
std::printf("%c\n", iter->get_upper()); // Prints A
iter->set('x');

std::puts(c.get()); // Prints Exxmple
std::puts(c.get_upper()); // Prints EXXMPLE

问题是,具有成员函数get_sourceget_upper等的“代理”类型没有明显可以存储的位置,并且需要迭代器返回对某物的引用,而不是值. (vector<bool>也有类似问题)

或者,我可以公开某种外壳容器或范围,或者公开完全独立的迭代器开始/结束函数。有没有人做过这样的事情并且知道什么效果很好?

【问题讨论】:

  • operator* 返回 T& 的要求适用于前向迭代器(C++11 24.2.5 前向迭代器 [forward.iterators] 第 1 段)。对于输入或输出迭代器,它不适用。
  • @Casey:在这种情况下,公开输入和/或输出迭代器是不够的——我想支持随机访问。
  • 看起来像是范围视图的工作
  • 根据我的经验,大多数只读算法在不返回引用的类似迭代器的对象上都能正常工作。显然,排序不起作用。代理类型习语很方便。

标签: c++ stl iterator


【解决方案1】:

我个人处理这类事情的方法是使用属性映射:我envision a system 的算法可以[可选地]为每个范围获取一个属性映射(或者实际上有时是多个属性映射) .这个想法是*it 产生一个 key (例如,它目前所做的T&),然后与将键转换为实际访问的 值 的属性映射一起使用时间>。例如,转换可以是产生算法当前行为的标识,并且是在没有属性映射时使用的良好默认值。上面的例子看起来像这样:

auto const cursor = c.begin();
std::printf("%c\n", c.map_source()(*cursor));
std::printf("%c\n", c.map_upper()(*cursor));
c.map_source()(*cursor, 'x');

std::copy(c.map_source(), c, std::ostreambuf_iterator<char>(std::cout));
std::copy(c.map_upper(), c, std::ostreambuf_iterator<char>(std::cout));
std::copy([](unsigned char c)->char{ return std::toupper(c); }, c,
          std::ostreambuf_iterator<char>(std::cout));

代码假定产生源和大写字符的属性映射分别使用c.map_source()c.map_upper() 获得。使用 std::copy() 的最后一个变体使用 lambda 函数作为属性映射。

遗憾的是,我仍然没有时间编写一个连贯的提案,以对 STL 算法进行各种改进。 ...我也没有将它们放在一起的实现(我有一个大约 10 年的 somewhat clunky implementation 并且没有从各种 C++11 功能中受益,这使得它更容易;另外,这个实现只专注于属性图,不使用我目前设想的界面)。

【讨论】:

  • 问题在于,这迫使人们放弃现有算法期望迭代器对或范围的大量工作。最终由标准委员会应用可能是一个有趣的概念,但我不会将其称为 C++11/14 及其标准库的惯用解决方案。
  • @BillyONeal:我当然同意它与当前算法不能很好地配合的评估。我正在讨论涉及的各种更改(上面的代码使用 Ranges SG 的 rangesproperty maps),这些想法通常很受欢迎。
  • 是的,我不是在抄袭这些想法或类似的东西。我只是说这并不能很好地回答今天的问题。
猜你喜欢
  • 1970-01-01
  • 2018-05-22
  • 2021-06-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-02-17
  • 2020-06-18
  • 2023-03-12
相关资源
最近更新 更多