【发布时间】:2019-08-30 23:51:44
【问题描述】:
我正在实现一个迭代器适配器,它允许处理保存void* 的旧数据类型,我想获得一个forward_iterator,它允许交换旧数据类型的值,方法是给用户一个保存在该结构中的真实指针的视图。示例:
auto it = iterator_adaptor<T*>(pos);
其中pos->object 是一个void*,它最初的类型是T*。事情是关于引用类型:
// within iterator_adaptor
typedef T*& reference;
// I want to promise that to the user.
typedef std::forward_iterator_tag iterator_category;
reference operator*() const { return static_cast<reference>(_pos->object); }
这会产生编译器错误,因为我无法将引用包装在不同类型的对象上。如果类型相关,我可以在引用之间或指针之间进行转换,但是知道_pos->object 指向@ 类型的对象,我怎么能以非未定义的行为方式将void* 左值转换为T*& 987654331@?
我能想到的唯一可能被编译器吞下的是:
return *reinterpret_cast<T**>(&_pos->object);
或者这个方向的东西,但必须以 100% 的概率将其定义为标准未定义的行为。
注意:我想返回 T*&,而不是 T&,因为每个 T 的某些语义是由其地址定义的(具体来说,有映射 @ 987654336@ 到它的地址,因为每个T::id() 对于T* 都是唯一的)。如果我返回T& 并且用户交换它们,地址和id 不再匹配,举一些可能破坏应用程序的例子。我宁愿允许用户在结构中交换每个T* 的位置(因为用户毕竟保存了指针;每个T 都是在插入结构之前动态创建的),例如个性化其排序,或者使用任何需要转发和输入迭代器的std 算法。
实际上,“交换”位置并不是那么重要,但是我想提供一个功能,将<algorithm> 库用于需要前向迭代器的算法。
【问题讨论】:
-
我要去另一个方向。我正在重新审视我的旧 C 代码接口,以使它们尽可能地键入。不让
void*活着.... -
你可能会返回一个包装器而不是一个真正的引用:
typedef my_ref_wrapper<T*> reference; -
@TedLyngmo 我实际上正在按照你说的做。我正在尝试再次输入所有内容。
-
@Jarod42 这不会产生 ForwardIterator。
-
typedef struct { void* ptr_ } A;工作......并且即使在 C 中也进行了类型检查。@Peregring-lk 太好了!这对我很有帮助。
标签: c++ casting reference lvalue