Since the std::forward_list
is implemented as a single-linked list, its iterator should be just a pointer to the underlying element ± some offset.
Is there a way to convert a pointer to an element on a list to the iterator to this element without iterating through the entire 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;
}
Short answer: Yes, I could hack a function
makeIterator
that does that:Essentially, it does some pointer arithmetic to derive the address of the underlying list node and constructs an iterator from the derived pointer. The function
learnOffset
returns the offset needed in the pointer arithmetics.See the long answer for details on how the function
learnOffset
is implemented. Note however, that this solution depends on the implementation of your C++ standard library. I am not aware of any public API function that does what you are asking for.Long answer
I studied the implementation of the forward list iterator in the file
/usr/include/c++/11/bits/forward_iterator.h
and specifically the implementation oftemplate<typename _Tp> struct _Fwd_list_iterator
. It exposes a public member variable that points at the node in the linked list:and is used for example from the dereferencing operator:
Reading the source code further suggests that the value stored in a list node is stored by value in the node itself. If so, there should be a constant offset between the pointer to that value and the list node itself. To test that, I wrote the function
learnOffset
:which returns
8
bytes. We can now directly call this function from the implementation ofmakeIterator
above.The above implementation of
learnOffset
leaves a lot to be desired. This code should just be considered a proof-of-concept.Edited: Made
learnOffset
a template and to return offset in bytes.