Does Stack have iterators in C++? - c++

From what I know, stack does not have iterators in C++. For example, this post (Does std::stack expose iterators?) explicitly states that stack does not have iterators. However, I was told by my supervisor that stack in c++ should have iterators since it is a standard data structure and you can do stack.begin() (However, from what I know, there's no such syntax in standard C++). How do I convince him? Why stack does not have iterators in C++?
Question#2: Thank you all for awesome answers. I think the question now comes down to: why doesn't it make sense to have iterators for stack?

You can convince your supervisor by advising your supervisor go and read section 23.6.5 of ISO/IEC-14882(2011), the specification for std::stack.
std::stack does not have iterators.

std::stack provides a strictly last-in-first-out view of the underlying container, and that's the point of it: to restrict the use of the underlying container to LIFO.
And so it does not provide iteration.
However, it does provide the underlying container as a protected member, which means that it's designed for being derived from. In your derived class you can provide iterators, and whatever you want. Also it's possible to just access that protected member of an ordinary std::stack, even without using any cast (namely via implicit conversion of member data pointer).
Re the added 2nd question,
” why doesn't it make sense to have iterators for stack?
It can make sense, but in most cases it would provide the non-LIFO access that std::stack is designed to remove, i.e. in most cases it would be at odds with the very purpose of std::stack.
For debugging, one's debugger will show the contents of a std::stack, so there's no big need to have direct support for doing it in code.
Example:
#include <iostream>
#include <stack>
namespace cppx {
using std::stack;
namespace hack {
template< class Item >
auto container_of( stack<Item> const& st )
-> typename stack<Item>::container_type const&
{
struct Hacked: stack<Item> { using stack<Item>::c; };
return st.*&Hacked::c;
}
} // namespace hack
template< class Item >
auto begin( stack<Item> const& st )
{ return hack::container_of( st ).begin(); }
template< class Item >
auto end( stack<Item> const& st )
{ return hack::container_of( st ).end(); }
} // namespace cppx
auto main()
-> int
{
using namespace std;
stack<int> st;
for( int const x : {3, 1, 4, 1, 5, 9, 2, 6, 5, 4} )
{
st.push( x );
}
using cppx::begin; using cppx::end;
for( auto it = begin( st ); it != end( st ); ++it )
{
cout << *it << " ";
}
cout << endl;
}
Since in this example begin and end are not placed in namespace std, a range based loop would not compile.
I didn't do that because the legality (validity) of specializing a standard function for a standard container, in namespace std, is an issue I don't want to get into here. I think it's not permitted, although specializing for one's own type would be OK. But I'm not sure.

std::stack is but a container adapter. It accepts a type of container (std::deque by default) as template parameter, and an instance of stack can be constructed from an instance of this container, but otherwise the underlying private container is not exposed and the stack itself does not have iteration facilities.

Related

Moving an std::unordered_map values to std::vector

Is there any way to move unordered_map values to a vector? All the ways I was able to find copy values (like in my example) instead of using something similar to std::move.
I would like to not copy values so I can retain uniqueness of shared_ptr foo, which I'll later change to unique_ptr.
class Class {
public:
std::shared_ptr <int> foo = std::shared_ptr <int> (new int (5));
};
int main() {
std::unordered_map <int, Class> mapOfObjects({
{1, Class()},
{2, Class()},
{3, Class()},
{4, Class()},
{5, Class()} });
std::vector <Class> someVector;
for (auto &object : mapOfObjects) {
someVector.push_back(object.second);
std::cout << "Is unique? " << ( someVector.back().foo.unique() ? "Yes." : "No.")
<< std::endl << std::endl;
}
}
Thank you in advance for all helpful answers.
You can certainly move shared_ptr from unordered_map to vector. All you need to do is to use std::move in your example:
someVector.push_back(std::move(object.second));
Keep in mind, after this operation, you might want to clear the map, as it now contains empty objects.
#SergeyA's answer already covers the essential part here, let me nevertheless add a solution based on range-v3, it shows where one part of the language is heading to with C++20.
#include <range/v3/view/map.hpp>
#include <range/v3/view/move.hpp>
using namespace ranges;
/* Setup mapOfObjects... */
const std::vector<Class> someVector = mapOfObjects | view::values | view::move;
The STL in its current shape isn't that bad either, but admittetly more verbose:
#include <algorithm>
#include <iterator>
std::vector<Class> someVector;
std::transform(std::move_iterator(mapOfObjects.begin()),
std::move_iterator(mapOfObjects.end()),
std::back_inserter(someVector),
[](std::pair<int, Class>&& entry){ return std::move(entry.second); });

Is there a C++ container for unique values that supports strict size checking?

I'm looking for a C++ container to store pointers to objects which also meets the following requirements.
A container that keeps the order of elements (sequence container, so std::set is not suitable)
A container that has a member function which return the actual size (As std::array::size() always returns the fixed size, std::array is not suitable)
A container that supports random accesses such as operator [].
This is my code snippet and I'd like to remove the assertions used for checking size and uniqueness of elements.
#include <vector>
#include <set>
#include "assert.h"
class Foo {
public:
void DoSomething() {
}
};
int main() {
// a variable used to check whether a container is properly assigned
const uint8_t size_ = 2;
Foo foo1;
Foo foo2;
// Needs a kind of sequential containers to keep the order
// used std::vector instead of std::array to use member function size()
const std::vector<Foo*> vec = {
&foo1,
&foo2
};
std::set<Foo*> set_(vec.begin(), vec.end());
assert(vec.size() == size_); // size checking against pre-defined value
assert(vec.size() == set_.size()); // check for elements uniqueness
// Needs to access elements using [] operator
for (auto i = 0; i < size_; i++) {
vec[i]->DoSomething();
}
return 0;
}
Is there a C++ container which doesn't need two assertions used in my code snippet? Or should I need to make my own class which encapsulates one of STL containers?
So a class that acts like a vector except if you insert, it rejects duplicates like a set or a map.
One option might be the Boost.Bimap with indices of T* and sequence_index.
Your vector-like indexing would be via the sequence_index. You might even be willing to live with holes in the sequence after an element is erased.
Sticking with STLyou could implement a bidirectional map using 2 maps, or the following uses a map and a vector:
Note that by inheriting from vector I get all the vector methods for free, but I also risk the user downcasting to the vector.
One way round that without remodelling with a wrapper (a la queue vs list) is to make it protected inheritance and then explicitly using all the methods back to public. This is actually safer as it ensures you haven't inadvertently left some vector modification method live that would take the two containers out of step.
Note also that you would need to roll your own initializer_list constructor if you wanted one to filter out any duplicates. And you would have to do a bit of work to get this thread-safe.
template <class T>
class uniqvec : public std::vector<T*>
{
private:
typedef typename std::vector<T*> Base;
enum {push_back, pop_back, emplace_back, emplace}; //add anything else you don't like from vector
std::map <T*, size_t> uniquifier;
public:
std::pair<typename Base::iterator, bool> insert(T* t)
{
auto rv1 = uniquifier.insert(std::make_pair(t, Base::size()));
if (rv1.second)
{
Base::push_back(t);
}
return std::make_pair(Base::begin()+rv1.first.second, rv1.second);
}
void erase(T* t)
{
auto found = uniquifier.find(t);
if (found != uniquifier.end())
{
auto index = found->second;
uniquifier.erase(found);
Base::erase(Base::begin()+index);
for (auto& u : uniquifier)
if (u.second > index)
u.second--;
}
}
// Note that c++11 returns the next safe iterator,
// but I don't know if that should be in vector order or set order.
void erase(typename Base::iterator i)
{
return erase(*i);
}
};
As others have mentioned, your particular questions seems like the XY problem (you are down in the weeds about a particular solution instead of focusing on the original problem). There was an extremely useful flowchart provided here a number of years ago (credit to #MikaelPersson) that will help you choose a particular STL container to best fit your needs. You can find the original question here In which scenario do I use a particular STL container?.

How to set two vector<unique_ptr<...>>'s equal to one another?

I am using Visual Studio 2012 C++ and I want to set two vectors with unique pointers equal to one another.
using namespace std;
vector<unique_ptr<Unit>> unitVector;
vector<unique_ptr<Unit>> nonDeadUnits;
.... (stuff added to unitVector) ....
for (auto unit = unitVector.begin(); unit != unitVector.end(); ++unit) {
if ((*unit)->health > 0) {
nonDeadUnits.push_back(*unit);
}
}
unitVector.clear();
unitVector = nonDeadUnits; // error here (see below error code)
I want to remove all of the units that have health less than 0, but if I try and directly remove them from the vector, I attempt to access memory that I shouldn't, killing the program. That is why I have opted to do it this way. The only problem is that unique_ptr does not allow the type of copying that I want. Here is the error:
error C2248: 'std::unique_ptr<_Ty>::operator =' : cannot access private member declared in class 'std::unique_ptr<_Ty>' c:\program files (x86)\microsoft visual studio 11.0\vc\include\xutility 2089
I would like to have unique_ptr's because the vectors call sub-class methods within a for loop later on, and it helps with overriding. So how do I set the vectors equal to one another or is there a better way?
The general idea is to use std::remove_if to swap elements within unitsVector, and then once all the dead units are at the end of the vector, you just chop them off.
#include <memory>
#include <vector>
struct Unit {
int health;
};
// The non-working version.
//
// void remove_dead_units(std::vector<std::unique_ptr<Unit>> &unitVector)
// {
// std::vector<std::unique_ptr<Unit>> nonDeadUnits;
// for (auto unit : unitVector)
// if (unit->health > 0)
// nonDeadUnits.push_back(unit);
// unitVector = nonDeadUnits;
// }
void remove_dead_units(std::vector<std::unique_ptr<Unit>> &unitVector)
{
auto isDead = [](const std::unique_ptr<Unit> &u) -> bool { return (u->health <= 0); };
auto newEnd = std::remove_if(unitVector.begin(), unitVector.end(), isDead);
unitVector.erase(newEnd, unitVector.end());
}
I'm sure there are other ways to do it, hewing more closely to what you tried (EDIT: in fact KerrekSB just posted one, using only a single std::move and a swap); but I think the "shuffle and chop" method is more modern-C++ish.
Perhaps the following logic would be simpler:
vector<unique_ptr<Unit>> unitVector = /* ... */;
vector<unique_ptr<Unit>> nonDeadUnits;
for (auto & p : unitvector)
{
if (p->health > 0) { nonDeadUnits.push_back(std::move(p)); }
}
unitVector.swap(nonDeadUnits);
Otherwise, the standard remove-erase idiom is probably more main-stream:
unitVector.erase(remove_if(unitVector.begin(), unitVector.end(),
[](unique_ptr<Unit> const & p) -> bool { return p->health <= 0; }),
unitVector.end());
The fast way to do this is with remove_if and erase, but that idiom violates DRY (don't repeat yourself) and I have seen people make subtle mistakes when using it (forgetting the 2nd iterator to erase passing (inadequate) test cases, then failing in production!)
My solution to this kind of problem -- filtering a std::vector for some property -- is to write a container-based algorithm to do it for me.
template<typename SeqContainer, typename Lambda>
SeqContainer&& remove_erase_if( SeqContainer&& c, Lambda&& test ) {
using std::begin; using std::end;
auto new_end = std::remove_if( begin(c), end(c), std::forward<Lambda>(test) );
c.erase( new_end, end(c) );
return std::forward<SeqContainer>(c);
}
now that you have a container based remove_erase_if, we can filter the list:
// const & is important, we don't want to copy a `unique_ptr`
remove_erase_if( unitVector, [&]( std::unique_ptr<Unit> const& unit ) {
return (unit->health() <= 0);
});
... and that is it. Everything with health() <= 0 is removed from the std::vector.
Other useful container based algorithms I find I use quite often include remove_erase and sort_unique_erase and binary_search. Amusingly, while the above code works std::vector, std::list and std::deque, I almost always use std::vector: but writing it to work with any sequential container is easier than writing it to work with a std::vector.
Another option for the design of these container algorithms is to take the container by value, and return it by value. This forces some std::move spam, but is basically equally efficient at runtime.

Customize an iterator for a wrapped list

I've got a class, memberlist, that contains a std::list of class memberinfo. These represents the peers on a network.
I use the class to add some functionality to the list.
I want to expose some iterators (begin and end) so that outside code can loop through my internal list and read their data. However, I want to have two ways of doing this - one that includes an element for the localhost, and one that doesn't.
What's a good way to do this?
I could put the local node first, then have like begin(showlocal=false) just give the second element instead of the first. Or someone suggested storing a pair of with the bool saying if it's local or not.
Any suggestions on a good way to do this? I'm not too great on advanced STL stuff yet.
Personally I would approach this in a different way and have your memberinfo have a way of telling you if it's local or not.
That way you're not specialising your collection class due to a specialisation of the contained objects. In fact you could just use a standard std::list<memberinfo>.
E.g.
class memberinfo
{
bool IsLocal( ) const;
}
Then you would choose whether you're interested in local members or not while you're iterating through the contained objects.
E.g.
std::list<memberinfo>::iterator it;
std::list<memberinfo> list;
for ( it = list.begin() ; it != list.end() ; it++ )
{
if ( it->IsLocal() )
{
// blah blah blah
}
else
{
// dum dee dum dee
}
}
As I said in comment to your question, I think your first solution is reasonable. However, I'm not sure that giving a parameter to begin is the best approach for discriminating the two cases. The major problem with this is that you cannot use your full collection (including the localhost member) as a range, meaning that you cannot use Boost.Range algorithms or the C++11 range-based for loop.
A simple solution would be to have two different member functions returning the appropriate range, as a pair of iterators. Boost.Range provides a sub_range class, which seems rather appropriate (you want to return a sub-range of the list of members). Here is a sample code using this approach:
#include <boost/range.hpp>
#include <iostream>
#include <string>
#include <vector>
struct MemberInfo
{
std::string name;
};
class MemberList
{
public:
typedef std::vector<MemberInfo>::iterator iterator;
typedef std::vector<MemberInfo>::const_iterator const_iterator;
MemberList()
: members_{MemberInfo{"local"}, MemberInfo{"foo"}, MemberInfo{"bar"}}
{}
boost::sub_range<std::vector<MemberInfo>> all() // includes localhost
{
return boost::sub_range<std::vector<MemberInfo>>(
members_.begin(), members_.end());
}
boost::sub_range<std::vector<MemberInfo> const> all() const
{
return boost::sub_range<std::vector<MemberInfo> const>(
members_.begin(), members_.end());
}
boost::sub_range<std::vector<MemberInfo>> some() // excludes localhost
{
return boost::sub_range<std::vector<MemberInfo>>(
++members_.begin(), members_.end());
}
boost::sub_range<std::vector<MemberInfo> const> some() const
{
return boost::sub_range<std::vector<MemberInfo> const>(
++members_.begin(), members_.end());
}
private:
std::vector<MemberInfo> members_;
};
Now, you can use either all() or some() depending on whether you want to include local or not, and both can be used as ranges:
int main()
{
MemberList ml;
for (MemberInfo mi : ml.all()) { std::cout << mi.name << '\n'; }
for (MemberInfo mi : ml.some()) { std::cout << mi.name << '\n'; }
}
And of course, you can still use iterators as usual:
std::find_if(ml.all().begin(), ml.all().end(), ...);
If you don't want to leak the fact that your members are stored in a std::vector, you can use any_range, which erases the underlying iterator type.

How to tell a std::priority_queue to refresh its ordering?

I have a priority queue of pointers to a struct city. I modify the objects pointed by these pointers outside the priority queue, and want to tell the priority queue to "reorder" itself according to the new values.
What should I do?
Example:
#include <iostream>
#include <queue>
using namespace std;
struct city {
int data;
city *previous;
};
struct Compare {
bool operator() ( city *lhs, city *rhs )
{
return ( ( lhs -> data ) >= ( rhs -> data ) );
}
};
typedef priority_queue< city *, vector< city * >, Compare > pqueue;
int main()
{
pqueue cities;
city *city1 = new city;
city1 -> data = 5;
city1 -> previous = NULL;
cities.push( city1 );
city *city2 = new city;
city2 -> data = 3;
city2 -> previous = NULL;
cities.push( city2 );
city1 -> data = 2;
// Now how do I tell my priority_queue to reorder itself so that city1 is at the top now?
cout << ( cities.top() -> data ) << "\n";
// 3 is printed :(
return 0;
}
This is a bit hackish, but nothing illegal about it, and it gets the job done.
std::make_heap(const_cast<city**>(&cities.top()),
const_cast<city**>(&cities.top()) + cities.size(),
Compare());
Update:
Do not use this hack if:
The underlying container is not vector.
The Compare functor has behavior that would cause your external copy to order differently than the copy of Compare stored inside the priority_queue.
You don't fully understand what these warnings mean.
You can always write your own container adaptor which wraps the heap algorithms. priority_queue is nothing but a simple wrapper around make/push/pop_heap.
If you need to keep an ordered collection you may consider the following solution: Use std::set and to update values remove the item, update its value and place it back into the set. This will give you O(log n) complexity for updating one item, which is the best you can in a usual heap structure (Assuming you had access to its internals to mass with the sift-up sift-down procedures).
The only downside to std::set will be the time for initializing a set with n items. (O(n log n) instead of O(n)).
Based on http://www.sgi.com/tech/stl/priority_queue.html it does not look like there is a way to do that, without emptying and re-inserting.
If you are willing to move away from priority_queue (but still want a heap), then you can use a vector, along with the make_heap, push_heap and pop_heap. See the Notes section in the page for priority_queue.
This is an old question but I wasn't fully satisfied with any of the answers when I wanted to do this myself. There is no need for any hacks. std::priority_queue contains all the machinery to do this legally and idiomatically.
std::priority_queue has two very helpful data members, c (the underlying container) and comp (the comparison predicate).
Equally helpfully, the standard mandates that the Container template type must be a model of SequenceContainer who's iterators are models of RandomAccessIterator.
This is helpful because the Iter argument type of std::make_heap have the same RandomAccessIterator model requirement.
This is a longwinded way of saying that std::priority_queue is a wrapper around a heap and that therefore std::make_heap(std::begin(c), std::end(c), comp) must be a valid expression.
The 'bad' news is that c and comp are protected. This is actually good news for two reasons:
You can't destroy the heap accidentally.
If you derive from std::priority_queue you can modify the heap intentionally.
So the trick is to derive your priority queue from std::priority_queue, in a member function, mutate the internal heap c any way you like and then call std::make_heap(std::begin(c), std::end(c), comp); to turn it back into a valid heap.
Is it not, generally, a bad idea to inherit from STL containers
Well, yes, but...
There are two reasons that this could be a bad idea for the young and/or unwary. Lack of polymorphic destructors and the risk of slicing.
Polymorphic destructors
There is actually no reasonable use case for owning a std container through a pointer to its base class. Containers are lightweight (when there is nothing in them) and cheaply moveable. You may be able to think of use cases, but I can guarantee that whatever you intended to do can be done better by encapsulating the container in another heap-allocated object. In well-designed code, this should never have become a concern. In any case, inheriting privately from the priority_queue template class removes this risk.
Slicing
Certainly there is a risk of slicing when we pass inherited objects around. The answer here is to inherit privately from the priority_queue base class, and then use using in the derived class to export only the parts of the base class's interface that we wish to share.
The example below has been updated to show this.
Below is an example from a real project.
Requirements:
Keep a queue of topics that a client must be notified changes to. Order the queue by the timestamp of the earliest time that this topic was notified. Do not allow duplicate topic names.
Here is a working demo:
#include <queue>
#include <string>
#include <chrono>
#include <cassert>
#include <iostream>
using topic_type = std::string;
using timestamp_clock = std::chrono::system_clock;
using timestamp_type = timestamp_clock::time_point;
struct notification {
topic_type topic;
timestamp_type timestamp;
};
bool topic_equals(const notification& l, const topic_type& r) {
return l.topic == r;
}
bool topic_equals(const topic_type& l, const notification& r) {
return l == r.topic;
}
bool age_after(const notification& l , const notification& r) {
return l.timestamp > r.timestamp;
}
bool age_after(const notification& l , const timestamp_type& r) {
return l.timestamp > r;
}
bool age_after(const timestamp_type& l , const notification& r) {
return l > r.timestamp;
}
struct greater_age
{
template<class T, class U>
bool operator()(const T& l, const U& r) const {
return age_after(l, r);
}
};
template<class T>
struct pending_queue_traits;
template<>
struct pending_queue_traits<notification>
{
using container_type = std::vector<notification>;
using predicate_type = greater_age;
using type = std::priority_queue<notification, container_type, predicate_type>;
};
class pending_notification_queue
: private pending_queue_traits<notification>::type
{
using traits_type = pending_queue_traits<notification>;
using base_class = traits_type::type;
public:
// export the constructor
using base_class::base_class;
// and any other members our clients will need
using base_class::top;
using base_class::pop;
using base_class::size;
bool conditional_add(topic_type topic, timestamp_type timestamp = timestamp_clock::now())
{
auto same_topic = [&topic](auto& x) { return topic_equals(topic, x); };
auto i = std::find_if(std::begin(c), std::end(c), same_topic);
if (i == std::end(c)) {
this->push(notification{std::move(topic), std::move(timestamp)});
return true;
}
else {
if (timestamp < i->timestamp) {
i->timestamp = std::move(timestamp);
reorder();
return true;
}
}
return false;
}
private:
void reorder() {
std::make_heap(std::begin(c), std::end(c), comp);
}
};
// attempt to steal only the base class...
void try_to_slice(pending_queue_traits<notification>::type naughty_slice)
{
// danger lurks here
}
int main()
{
using namespace std::literals;
auto pn = pending_notification_queue();
auto now = timestamp_clock::now();
pn.conditional_add("bar.baz", now);
pn.conditional_add("foo.bar", now + 5ms);
pn.conditional_add("foo.bar", now + 10ms);
pn.conditional_add("foo.bar", now - 10ms);
// assert that there are only 2 notifications
assert(pn.size() == 2);
assert(pn.top().topic == "foo.bar");
pn.pop();
assert(pn.top().topic == "bar.baz");
pn.pop();
// try to slice the container. these expressions won't compile.
// try_to_slice(pn);
// try_to_slice(std::move(pn));
}
The stl's containers don't provide as fast as possible updatable priority queues.
#Richard Hodges: make_heap takes O(n) complexity, and the push_heap function doesn't tell you where the provided element was stored, making a quick update of a single element impossible (you need O(n) to find it).
I have implemented a high-performance updatable priority queue (an update costs O(log n), twice as fast as using an std::set) and made it available on github.
This is how you would typically use it :
better_priority_queue::updatable_priority_queue<int,int> pQ;
pQ.push(0, 30); // or pQ.set(0, 30)
pQ.push(1, 20);
pQ.push(2, 10);
pQ.update(2, 25); // or pQ.set(2, 25)
while(!pQ.empty())
std::cout << pQ.pop_value().key << ' ';
// Outputs: 0 2 1