Null
Null

Reputation: 389

Iterator aware objects in std::list

I have a list of objects:

std::list<A> objects;

In order to trigger an async operation that will remove them from the list based on some condition, The objects need to be aware of their location in the list:

A::A(std::list<A>::iterator it);

How can I pass iterator to constructor when adding items to the list?

objects.emplace(<the iterator to new item>);

Initializing the member iterator of class A cannot be done later, even the constructor may trigger the deletion operation, so it needs this member while construction.

Possible solutions that I have thought (brings extra complexity):

1:

objects.emplcae(A(objects.end())); // dummy object
A a{ std::prev(objects.end()) };
std::swap(a, object.back());

2:

objects.emplace();
objects.back().set_iterator(std::prev(objects.end()));
objects.back().run(); // Moved the work from constructor to this function (against RAII)

3: Try to get iterator based on the address of this.

Upvotes: 1

Views: 132

Answers (1)

Dmitry Kuzminov
Dmitry Kuzminov

Reputation: 6584

There is a chicken and egg problem that you have to resolve: the A class wants the iterator to be ready before the object is constructed, while the iterator assumes that some sort of an element is constructed already.

One way to solve this problem is to introduce an additional level of indirection, for example to store not the instances of A but the pointers (smart pointers) instead. Another way is to use placement new: first to allocate an item in list without constructing the object (just allocate the memory), then construct the object inplace with the iterator provided. The simplest solution would be to separate in time the construction of A and setting the iterator (A::setIterator(std::list<A>::iterator&) method).

I would also recommend you to implement that as a Factory method that takes a list (an all the ingredients), and does all this error-prone stuff in one place. The Factory method should be the friend of A while the constructor A::A should be private. This would prevent you from other incorrect ways to construct A.

Upvotes: 3

Related Questions