如何实现一个公开多个范围的容器
How does one implement a container which exposes multiple ranges?
我有一个容器,它(除其他外)公开了一个字符串缓冲区,以及该字符串缓冲区的大写版本。(好吧,这不仅仅是大写,但它在概念上是相似的)我想允许调用者做一些类似的事情:
container c("Example");
auto const iter = c.begin() + 2;
std::printf("%cn", iter->get_source()); // Prints a
std::printf("%cn", iter->get_upper()); // Prints A
iter->set('x');
std::puts(c.get()); // Prints Exxmple
std::puts(c.get_upper()); // Prints EXXMPLE
问题是,具有成员函数get_source
、get_upper
等的"代理"类型没有明显的存储位置,并且需要迭代器来返回对某个对象的引用,而不是值。(vector<bool>
也有类似的问题)
或者,我可以公开某种shell容器或范围,或者公开完全独立的迭代器开始/结束函数。有没有人有做这种事情的经验,知道什么效果好?
我个人处理这类事情的方法是使用属性映射:我设想了一个算法系统,它可以[可选]为每个范围获取一个属性映射(有时实际上是多个属性映射)。其思想是*it
产生一个键(例如,它当前所做的T&
),然后与属性映射一起使用,属性映射将键转换为实际访问的值。例如,转换可以是产生算法的当前行为的身份,以及在没有属性映射时使用的良好默认值。上面的例子看起来像这样:
auto const cursor = c.begin();
std::printf("%cn", c.map_source()(*cursor));
std::printf("%cn", 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年的历史了,没有从各种C++11功能中受益,这些功能使它变得更容易;而且,这个实现只专注于属性映射,不使用我目前设想的接口)。
相关文章:
- 为左值和右值的包装器实现C++范围
- 基于范围的变换以实现正常循环
- 实现基于链表的堆栈的基于范围的 for 循环
- 避免在基于反向范围的for循环实现中悬挂参考
- 如何使用C++范围来实现numpy.ndindex?
- 范围修剪视图实现不适用于反向视图
- 实现编译检查以避免C++嵌套范围
- 私有在函数定义/实现的返回值范围内是什么意思 (c++)?
- 为什么此范围为Vectors求和的实现速度较慢
- C 中的快速范围搜索实现
- 使用范围V3视图来实现begin()/end()方法
- 在最少的操作中实现字符串所有字符的相同频率。(所有字符的范围从'a'到"z")
- 如何实现我的自定义范围循环
- 实现Boost范围适配器REVERSED_IF
- GCC 4.4 不实现 C++11 范围循环.它还支持哪些其他范围循环语法
- 如何实现一个公开多个范围的容器
- 交换实现:效率和适用范围?
- 使用提升范围实现LINQ选择
- 如何使用范围 v3 范围实现平面地图
- 它是安全锁/范围保护实现