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
makeIteratorthat 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
learnOffsetreturns the offset needed in the pointer arithmetics.See the long answer for details on how the function
learnOffsetis 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.hand 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
8bytes. We can now directly call this function from the implementation ofmakeIteratorabove.The above implementation of
learnOffsetleaves a lot to be desired. This code should just be considered a proof-of-concept.Edited: Made
learnOffseta template and to return offset in bytes.