Is there a way to delete an element from an STL container (be it list, vector, ...) only via an iterator pointing to the element to be deleted, but without providing the container object it resides in (i.e. without directly using the container memberfunction container<T>::iterator container<T>.erase(container<T>::iterator)?
(Follow-up to this question)
No, this is not possible.
Imagine what would have to happen in order for the standard to provide a way to do this. std::vector<T>::iterator could not be a simple T*. Instead it would have to contain enough information for the library to be able to "find" the vector to which it belongs, such as a pointer to the vector itself. Thus, if the standard imposed a requirement to make it possible to delete an element given only an iterator, it would force the standard library to add overhead that would slow down all users of the container.
Related
i have made a custom class to implement a std::vector.
My class has Forward iterator support. I'd like to know how I can implement a vector.insert like method that allows me to insert an element at any position inside the vector.
I can't use allocator, but i'd like to know if the insert method can be done with iterators and, if it is possible, how can it be done?
To implement insert you need to move/copy all elements post the insertion point one element (possibly allocating new memory and moving all members if your internal storage is not large enough), then insert the new element in the "hole" you just made.
Note that this (of course) invalidates existing iterators.
I need to iterate trough the contents of the internal container, however the only method that allows me to access it is constant:
const _Container& _Get_container() const
{ // get reference to container
return (c);
}
So I can only get const iterator from the internal vector's begin().Is there any way around this?
You can use a const_iterator to iterate over elements just fine, you just can't modify them.
If you do want to modify the objects, there's no way to do it without invoking undefined behavior - modifying an object declared as const is illegal.
No, there is no such way. The idea behind std::stack (and similar adaptors) is that you will only use the stack interface. And a generic stack only allows inspection of the top element.
So technically, you don't want a "stack," you want an "iterable stack." And the standard library does not provide a container/adaptor for that, so you'll have to resort to one of
implementing your own
using a plain container and maintaining the stack-like access manually
Side note: I really wish the adaptors actually provided iteration functionality; after all, they're only adaptors, so they are guaranteed to be backed by an appropriate container (or they could at least provide iteration as long as the backing container does). But it's not currently part of the standard.
Is there any simple/elegant way in C++11, via STL or boost, to make an element-type "smart" so that an instance of it always knows which container it belongs to and has member functions for a sort of "auto-removal" which also takes care of updating the container it is part of?
The real case is that I have a callback C-function (from a C library) being called after a given request has been completed. This function accepts a raw pointer to the element which has been processed. Now what I want is to remove this element from the list it belongs to and move it to another list.
I know I could store a pointer to the container in the element itself and when the callback is called I could iterate over that container until I find the element, then remove it and call newlist.push_back(object). Given that one element must live in one container (and only one), I wonder if there's something more elegant.
Boost's intrusive containers implement that functionality.
This requires specific containers as well as objects specifically designed to work with the containers, however.
I need to replace specific key values, while the rest of the value_type is left untouched. What I actually need to do, is copy the value, erase the entry and insert it with changed key value again. This is absolutely bad. I need to copy the whole value_type twice, and deallocate/allocate again.
Why the standard doesn't define methods like this:
// returns count of exchanged keys
size_type exchange_key(key_type const& x, key_type const& y);
// returns count of replaced keys
size_type replace_key(key_type const& old_key, key_type const& new_key);
Is there anything I'm missing?
I don't why it was not added in the first place, and i understand that it is too bad. I guess they just added what they felt was absolutely necessary.
I think i have read somewhere that Boost.MultiIndex provided this ability.
Associative containers are implemented in a way that does not allow to change the 'key' in an efficient manner. To make this explicit it does not provide convienence methods to replace a key. The associative container would also have to remove and insert again under the covers.
I think this is an abstraction problem. The standard doesn't say exactly how the containers are to be implemented, it only specifies the maximum complexity of some of the operations and leaves the rest to the implementation.
If the standard were to add a replace_key function, it would also have to specify that this should have a different complexity than the existing erase-insert combination. How can it do that without leaking implementation details? If the function isn't guaranteed to be faster on all implementations, it is pretty useless.
When you say that it would obviously be faster, you make assumptions about implementation details that the standard tries to avoid.
Now, you can, with .extract(key) (since C++17).
https://en.cppreference.com/w/cpp/container/map/extract
This is because changing a key could affect the structure of an associative containers. Notably, std::map, which is a typically Red-Black tree, the tree structure mostly will be changed once you modify a key (e.g., rotating sub trees). In some data structures, even such dynamic changes are disallowed. So, it is challenging to expose such operation as a standard in an associative container.
Regarding the overhead you concerned, once you have value_type as a pointer or reference, the overhead of deleting/inserting a pair isn't too bad.
Well, honestly behind the screens it would result into an insert and delete operation anyhow, with the sole difference that the value-part will not be copied. While this seems to be your biggest concern, unless your object is very heavy on copying, in a large container, the update operation to re-stabilize the ordered container will be heavier anyhow.
Now this would require some important changes however going further than the associative containers, the two most important I can see are:
The std::pair class needs an update, because you must be able to update the key without creating a new pair (as this would also copy the value object).
You need an update function that removes a pair from the tree, calls the new logic from 1., and reinserts it.
I think the main problem lies with the first one, as std::pair is at the moment actually a very simple wrapper, and your proposal would delete that principle and add some (unnecessary) complexity to it. Also note that call 2 does not actually add new functionality but wraps a system the developer could manage himself easily through references and the like. If they would add all this wrapping to std, it would become a really huge bloated piece of library.
If you want this principle, you should look for more complex libraries (probably boost has some). Or you should simply use a reference/shared_ptr as your value_type.
Given an STL container (you may also take boost::unordered_map and boost::multi_index_container into account) that is non-contiguous, is it guaranteed that the memory addresses of the elements inside the container never changes if no element is removed, (but new ones can be added)?
e.g.
class ABC { };
//
//...
//
std::list<ABC> abclist;
ABC abc;
abclist.insert(abc);
ABC * abc_ptr = &(*abclist.begin());
In other word will abc_ptr be pointed to abc throughout the execution, if I do not remove abc from abc_list.
I am asking this because I am going to wrap the class ABC in C++/Cli, so I need pointers to the ABC instances in the wrapper class. ABC is a simple class and I want the container to handle the memory. If the answer is no then I will use std::list<ABC*>.
std::list, std::set, and std::map guarantee that the iterators (including simple pointers) will not be invalidated when a new element is added or even removed.
As Armen mentioned std::list, std::set, and std::map are guaranteed to only invalidate the removed iterator. In the case of boost::unodered_map, the modifiers may indeed invalidate iterators.
http://www.boost.org/doc/libs/1_38_0/doc/html/boost/unordered_map.html
The C++ Standard places stringent rules on the validity of references / iterators. For each container, each method documents which elements may be moved (invalidating references and iterators).
The Node Based Containers: list, map, set, multimap and multiset guarantee that references and iterators to elements will remain valid as long as the element is not removed from the container.
Your use case is therefore one of the corner cases where using a list for storage is good, because of the invalidation guarantees that list offer.
I think it's better to use std::list <shared_ptr <ABC> > instead of passing a pointer.
It's good practice to delegate memory management (see scott meyers effective c++)
This has mulitple advantages:
you can share them and pass them without the headache of freeing them
garbage collection of your pointers
you don't pass a pointer in the first place