由于std::forward_list
是作为一个单链表实现的,它的迭代器应该只是一个指向底层元素的指针±某个偏移量。
有没有一种方法可以将指向列表中某个元素的指针转换为指向该元素的迭代器,而无需迭代整个列表?
#include <forward_list>
template<typename T>
typename std::forward_list<T>::iterator makeIterator(T *element)
{
// magic here
}
int main()
{
std::forward_list<int> list;
list.emplace_front(101);
auto i = makeIterator(&list.front());
return i == list.begin() ? 0 : 1;
}
3条答案
按热度按时间bihw5rsg1#
简短回答:是的,我可以破解一个函数
makeIterator
来实现这一点:实际上,它执行一些指针运算来导出底层列表节点的地址,并根据导出的指针构造一个迭代器。函数
learnOffset
返回指针运算中所需的偏移量。关于
learnOffset
函数是如何实现的详细信息,请参阅详细答案。但是请注意,此解决方案取决于您的C++标准库的实现。我不知道有任何公共API函数可以实现您所要求的功能。长长的回答
我研究了
/usr/include/c++/11/bits/forward_iterator.h
文件中的forward列表迭代器的实现,特别是template<typename _Tp> struct _Fwd_list_iterator
的实现,它公开了一个指向链表中节点的公共成员变量:例如,从取值运算符中使用:
阅读源代码可以进一步发现,存储在列表节点中的值是 by value 存储在节点本身中的。如果是这样,那么在指向该值的指针和列表节点本身之间应该有一个常量偏移量。为了测试这一点,我编写了函数
learnOffset
:返回
8
字节,我们现在可以直接从上面makeIterator
的实现中调用这个函数。上面的
learnOffset
实现还有很多需要改进的地方。这段代码只应被视为概念验证。**已编辑:**使
learnOffset
成为模板并返回偏移量(以 * 字节 * 为单位).mspsb9vt2#
std::forward_list
的迭代器可能是 List 的 Node。遗憾的是,没有兼容的方法来访问 Node 的结构。如果你有一个特定的编译器,并且知道它的底层 Node 和
iterator
实现,那么你可以简单地用一些简单的指针算法来访问它。所以,基本上是的,可能的,但这是完全不相容的和高度危险的。
那么,答案是。以给定的函数原型,这是不可能的。
如果你改变了函数的原型,并给它一个对列表的引用,那么我们就可以简单地沿着完整的
std::forward_list
迭代并比较指针。这可能如下所示:
moiiocjp3#
通常不可能将指针转换为迭代器(不搜索整个容器/范围)。这只可能用于 * 连续迭代器 *,并且
std::forward_list
不是连续容器。