How to initialize std stack with std vector? - c++

I need to put an std::vector into an std::stack.
Here is my method so far(I am building a card game) :
void CardStack::initializeCardStack(std::vector<Card> & p_cardVector) {
m_cardStack = std::stack<Card>();
//code that should initialize m_cardStack with p_cardVector
}
Note : I cannot change my method signature because it is a imposed by a teacher...
Do I have to iterate over the whole vector ? What is the most efficient way to do this ? The documentation.
I have tried Jens answer but it didn't work.

std::stack doesn't have a constructor which accepts iterators, so you could construct a temporary deque and initialize the stack with this:
void ClassName::initializeStack(std::vector<AnotherClass> const& v) {
m_stackAttribute = std::stack<AnotherClass>( std::stack<AnotherClass>::container_type(v.begin(), v.end()) );
}
However, this copies each element into the container. For maximum efficiency, you should also use move-semantics to eliminate copies
void ClassName::initializeStack(std::vector<AnotherClass>&& v) {
std::stack<AnotherClass>::container_type tmp( std::make_move_iterator(v.begin()), std::make_move_iterator( v.end() ));
m_stackAttribute = std::stack<AnotherClass>( std::move(tmp) );
}

The most efficient way is not using an std::stack at all and just use a std::vector or even better for this use a std::deque.
I've seen and written a lot of C++ code (a lot) but I've yet to find any use for the stack stuff (any meaningful use, that is). It would be different if the underlying container could be changed or having its container type determined at runtime, but this is not the case.
To copy the elements from an std::vector into a std::deque you can just use
std::deque<T> stack(vec.begin(), vec.end());
This will allow the implementation to use the most efficient way to copy the elements.
To explicitly answer your question: yes, the only way to put elements in a stack is to push them in with a loop. This is not efficient but the stack interface doesn't define anything else. However who wrote code accepting an std::stack parameter should be fired (unless s/he promises that it will never happen again) and its code reverted to something more sensible: you would get the same (absence of) "flexibility" but a better interface.
The design problem of stack is that it's parametrized on the underlying container type while instead (to have any meaning) should have been parametrized on the contained element type and receving in the constructor a container for that type (thus hiding the container type). In its present form is basically useless.

Related

remove_if without the need of move and copy semantics

Here is what a typical vector remove-erase operation looks like :
auto toErase = std::remove_if(vec.begin(), vec.end(),
[val](obj_t const& obj) { return obj.myval == val; }
); // This actually moves objects around !
vec.erase(toErase, vec.end());
This works fine in the majority of cases, but I am faced with the case where obj_t type does not allow move or copy semantics. Objects are inserted with vec.emplace_back(), and I am looking for an alternative to remove_if that doesn't need either copy or move.
Does it already exist somewhere ? If not, how would it be built ?
If object is non-movable/copyable how do you expect to rearrange objects in the vector? Vector is a contiguous container - so you cannot erase an element in the middle without shifting the ending.
To resolve the issue, either make the object movable/copyable, wrap it in unique_ptr (thus making it movable), or use one of map/set/unordered_map containers as those don't relocate objects unlike std::vector
It is not possible to remove from std::vector without copy or move support: how will you handle case, when you delete something from the middle? You can use for example std::list<Class> or std::vector<std::shared_ptr<Class>> instead of std::vector<Class>.
Actually, if the main problem around remove_if: I recommend you use shared_ptr or unique_ptr

Can one capture the reallocations of std::vector?

I know that push_back() on an std::vector can cause reallocation and therefore invalidate iterators in the pointer. Is there a way of installing a hook on reallocations (which presumably happen very seldom) so that I can adjust iterators appropriately?
Ideally something like this:
class hook; // forward
std::vectorwithhook<T,hook> v;
auto pointer = v.end();
template<> class hook<T> {
void operator()(T *old, T *new) { pointer += new-old; }
}
and then I can push_back() on v and play with pointer with no fear.
IMHO the easiest way to do this would be to have your vectorwithhook::push_back return the new end() and use it like:
pointer = v.push_back(new_item);
NOTE: you would have to do this for all members that change content of the vector (e.g. emplace_back, pop_back, insert etc...)
Alternatively, it should also be possible by creating your own allocator type, which will take a reference to iterator and the container in constructor and update it every time allocator::allocate(...) or allocator::dellocate(...) is called. NOTE that this goes against the principals of STL that was designed to have iterators, containers, allocators separate from one another...
P.S. none of this sounds like a good idea tbh, I would think about reworking the code to avoid keeping the end() iterator instead of doing any of this.

Writing a modern function interface to "produce a populated container"

When I cut my teeth on C++03, I learned several approaches to writing a "give me the collection of things" function. But each has some setbacks.
template< typename Container >
void make_collection( std::insert_iterator<Container> );
This must be implemented in a header file
The interface doesn't communicate that an empty container is expected.
or:
void make_collection( std::vector<Thing> & );
This is not container agnostic
The interface doesn't communicate that an empty container is expected.
or:
std::vector<Thing> make_collection();
This is not container agnostic
There are several avenues for unnecessary copying. (Wrong container type, wrong contained type, no RVO, no move semantics)
Using modern C++ standards, is there a more idiomatic function interface to "produce a populated container"?
The first approach is type erasure based.
template<class T>
using sink = std::function<void(T&&)>;
A sink is a callable that consumes instances of T. Data flows in, nothing flows out (visible to the caller).
template<class Container>
auto make_inserting_sink( Container& c ) {
using std::end; using std::inserter;
return [c = std::ref(c)](auto&& e) {
*inserter(c.get(), end(c.get()))++ = decltype(e)(e);
};
}
make_inserting_sink takes a container, and generates a sink that consumes stuff to be inserted. In a perfect world, it would be make_emplacing_sink and the lambda returned would take auto&&..., but we write code for the standard libraries we have, not the standard libraries we wish to have.
Both of the above are generic library code.
In the header for your collection generation, you'd have two functions. A template glue function, and a non-template function that does the actual work:
namespace impl {
void populate_collection( sink<int> );
}
template<class Container>
Container make_collection() {
Container c;
impl::populate_collection( make_inserting_sink(c) );
return c;
}
You implement impl::populate_collection outside the header file, which simply hands over an element at a time to the sink<int>. The connection between the container requested, and the produced data, is type erased by sink.
The above assumes your collection is a collection of int. Simply change the type passed to sink and a different type is used. The collection produced need not be a collection of int, just anything that can take int as input to its insert iterator.
This is less than perfectly efficient, as the type erasure creates nearly unavoidable runtime overhead. If you replaced void populate_collection( sink<int> ) with template<class F> void populate_collection(F&&) and implemented it in the header file the type erasure overhead goes away.
std::function is new to C++11, but can be implemented in C++03 or before. The auto lambda with assignment capture is a C++14 construct, but can be implemented as a non-anonymous helper function object in C++03.
We could also optimize make_collection for something like std::vector<int> with a bit of tag dispatching (so make_collection<std::vector<int>> would avoid type erasure overhead).
Now there is a completely different approach. Instead of writing a collection generator, write generator iterators.
The first is an input iterator that call some functions to generate items and advance, the last is a sentinal iterator that compares equal to the first when the collection is exhasted.
The range can have an operator Container with SFINAE test for "is it really a container", or a .to_container<Container> that constructs the container with a pair of iterators, or the end user can do it manually.
These things are annoying to write, but Microsoft is proposing Resumable functions for C++ -- await and yield that make this kind of thing really easy to write. The generator<int> returned probably still uses type erasure, but odds are there will be ways of avoiding it.
To understand what this approach would look like, examine how python generators work (or C# generators).
// exposed in header, implemented in cpp
generator<int> get_collection() resumable {
yield 7; // well, actually do work in here
yield 3; // not just return a set of stuff
yield 2; // by return I mean yield
}
// I have not looked deeply into it, but maybe the above
// can be done *without* type erasure somehow. Maybe not,
// as yield is magic akin to lambda.
// This takes an iterable `G&& g` and uses it to fill
// a container. In an optimal library-class version
// I'd have a SFINAE `try_reserve(c, size_at_least(g))`
// call in there, where `size_at_least` means "if there is
// a cheap way to get the size of g, do it, otherwise return
// 0" and `try_reserve` means "here is a guess asto how big
// you should be, if useful please use it".
template<class Container, class G>
Container fill_container( G&& g ) {
Container c;
using std::end;
for(auto&& x:std::forward<G>(g) ) {
*std::inserter( c, end(c) ) = decltype(x)(x);
}
return c;
}
auto v = fill_container<std::vector<int>>(get_collection());
auto s = fill_container<std::set<int>>(get_collection());
note how fill_container sort of looks like make_inserting_sink turned upside down.
As noted above, the pattern of a generating iterator or range can be written manually without resumable functions, and without type erasure -- I've done it before. It is reasonably annoying to get right (write them as input iterators, even if you think you should get fancy), but doable.
boost also has some helpers to write generating iterators that do not type erase and ranges.
If we take our inspiration from the standard, pretty much anything of the form make_<thing> is going to return <thing> by value (unless profiling indicates otherwise I don't believe returning by value should preclude a logical approach). That suggests option three. You can make it a template-template if you wish to provide a bit of container flexibility (you just have to have an understanding as to whether the allowed container is associative or not).
However depending on your needs, have you considered taking inspiration from std::generate_n and instead of making a container, provide a fill_container functionality instead? Then it would look very similar to std::generate_n, something like
template <class OutputIterator, class Generator>
void fill_container (OutputIterator first, Generator gen);
Then you can either replace elements in an existing container, or use an insert_iterator to populate from scratch, etc. The only thing you have to do is provide the appropriate generator. The name even indicates that it expects the container to be empty if you're using insertion-style iterators.
You can do this in c++11 without container copying. Move constructor will be used instead of a copy constructor.
std::vector<Thing> make_collection()
I don't think there is one idiomatic interface to produce a populated container, but it sounds like in this case you simply need a function to construct and return a container. In that case you should prefer your last case:
std::vector<Thing> make_collection();
This approach will not produce any "unnecessary copying", as long as you are using a modern C++11-compatible compiler. The container is constructed in the function, then moved via move semantics to avoid making a copy.

Why doesn't emplace/_front/_back return a reference?

When using std::vectors, std::lists (or other STL containers), I happen to often write this, for code shortness (rather than putting explicit vec[index] every time) and memory allocation efficiency (avoiding a copy/move), and I suppose I'm not the only one to do such:
std::vector<A> vec;
vec.emplace_back();
A &element = vec[vec.size()-1];
element.prop = "value";
Why doesn't STL containers' emplace, emplace_back and emplace_front methods return a T&? It would allow one to write simply this rather than using a shady vec.size()-1:
std::vector<A> vec;
A &element = vec.emplace_back();
element.prop = "value";
This has been fixed in C++17.
Your example
std::vector<A> vec;
A &element = vec.emplace_back();
element.prop = "value";
is valid C++17 code.
You have member methods to access those objects, since you know where they have been inserted. Namely front() and back().
Some other functions (e.g. map::insert) would return an iterator because you don't know how to access the inserted element in constant time. In the case of emplace, you do know.
Another reason for not returning anything might be performance (most of the time you would not use the returned value). And in C++ , you pay for what you use.
You do not need it. Write this:
template<class C, class...Args>
auto emplace_back(C& c, Args&&...args)->decltype(c.back()){
c.emplace_back(std::forward<Args>(args)...);
return c.back();
}
and you have the semantics you want without having to modify the container interface.
Just:
emplace_back(vec).prop = "foo";
Two arguments for choosing this signature:
API symmetry. These APIs are symmetric with pop_back, pop_front and push and pop as implemented for queues. These functions (the pop functions) have a situation where an element can be lost in the presence of an exception (i.e. the element is removed from the collection, but before it is returned an exception occurs (e.g. if the object's constructor can throw).
By implementing this functionality (read element and pop element) as two separate functions, both can be implemented transactionally.
SRP. It is a good design guideline, that if you describe the behavior of a function and need to use the word "and", you have broken SRP and should probably split it in two (i.e. A function that "appends an element at the end and returns a reference to it" should probably be written as two functions "add an element at the end" and "return element at the end" - both of which can offer at least weak exception guarantees to client code).
I am not sure if these criteria were applied for the design, but I remember the exception guarantee argument given in a lecture on exception safety.
in c++ 11 you can use:
m.emplace(val1, val2).first
to get a reference to the returned iterator, then:
m.emplace(val1, val2).first->first
and
m.emplace(val1, val2).first->second
to access map's k and v
:)

Best way to return list of objects in C++?

It's been a while since I programmed in C++, and after coming from python, I feel soooo in a straight jacket, ok I'm not gonna rant.
I have a couple of functions that act as "pipes", accepting a list as input, returning another list as output (based on the input),
this is in concept, but in practice, I'm using std::vector to represent the list, is that acceptable?
further more, I'm not using any pointers, so I'm using std::vector<SomeType> the_list(some_size); as the variable, and returning it directly, i.e. return the_list;
P.S. So far it's all ok, the project size is small and this doesn't seem to affect performance, but I still want to get some input/advice on this, because I feel like I'm writing python in C++.
The only thing I can see is that your forcing a copy of the list you return. It would be more efficient to do something like:
void DoSomething(const std::vector<SomeType>& in, std::vector<SomeType>& out)
{
...
// no need to return anything, just modify out
}
Because you pass in the list you want to return, you avoid the extra copy.
Edit: This is an old reply. If you can use a modern C++ compiler with move semantics, you don't need to worry about this. Of course, this answer still applies if the object you are returning DOES NOT have move semantics.
If you really need a new list, I would simply return it. Return value optimization will take care of no needless copies in most cases, and your code stays very clear.
That being said, taking lists and returning other lists is indeed python programming in C++.
A, for C++, more suitable paradigm would be to create functions that take a range of iterators and alter the underlying collection.
e.g.
void DoSomething(iterator const & from, iterator const & to);
(with iterator possibly being a template, depending on your needs)
Chaining operations is then a matter of calling consecutive methods on begin(), end().
If you don't want to alter the input, you'd make a copy yourself first.
std::vector theOutput(inputVector);
This all comes from the C++ "don't pay for what you don't need" philosophy, you'd only create copies where you actually want to keep the originals.
I'd use the generic approach:
template <typename InIt, typename OutIt>
void DoMagic(InIt first, InIt last, OutIt out)
{
for(; first != last; ++first) {
if(IsCorrectIngredient(*first)) {
*out = DoMoreMagic(*first);
++out;
}
}
}
Now you can call it
std::vector<MagicIngredients> ingredients;
std::vector<MagicResults> result;
DoMagic(ingredients.begin(), ingredients.end(), std::back_inserter(results));
You can easily change containers used without changing the algorithm used, also it is efficient there's no overhead in returning containers.
If you want to be really hardcore, you could use boost::tuple.
tuple<int, int, double> add_multiply_divide(int a, int b) {
return make_tuple(a+b, a*b, double(a)/double(b));
}
But since it seems all your objects are of a single, non-polymorphic type, then the std::vector is all well and fine.
If your types were polymorphic (inherited classes of a base class) then you'd need a vector of pointers, and you'd need to remember to delete all the allocated objects before throwing away your vector.
Using a std::vector is the preferably way in many situations. Its guaranteed to use consecutive memory and is therefor pleasant for the L1 cache.
You should be aware of what happends when your return type is std::vector. What happens under the hood is that the std::vector is recursive copied, so if SomeType's copy constructor is expensive the "return statement" may be a lengthy and time consuming operation.
If you are searching and inserting a lot in your list you could look at std::set to get logarithmic time complexity instead of linear. (std::vectors insert is constant until its capacity is exceeded).
You are saying that you have many "pipe functions"... sounds like an excellent scenario for std::transform.
Another problem with returning a list of objects (opposed to working on one or two lists in place, as BigSandwich pointed out), is if your objects have complex copy constructors, those will called for each element in the container.
If you have 1000 objects each referencing a hunk of memory, and they copy that memory on Object a, b; a=b; that's 1000 memcopys for you, just for returning them contained in a container. If you still want to return a container directly, think about pointers in this case.
It works very simple.
list<int> foo(void)
{
list<int> l;
// do something
return l;
}
Now receiving data:
list<int> lst=foo();
Is fully optimal because compiler know to optimize constructor of lst well. and
would not cause copies.
Other method, more portable:
list<int> lst;
// do anything you want with list
lst.swap(foo());
What happens: foo already optimized so there is no problem to return the value. When
you call swap you set value of lst to new, and thus do not copy it. Now old value
of lst is "swapped" and destructed.
This is the efficient way to do the job.