i've been trying to implement an iterator to my stack like this :
#include <iostream>
#include <stack>
#include <deque>
template <typename T, class container=std::deque<T>>
class MutantStack : public std::stack
{
public:
MutantStack(){}
~MutantStack(){}
MutantStack(const MutantStack &stack)
{
*this = stack;
}
typedef typename std::deque::iterator iterator;
};
but i couldn't make a begin and end iterator, how i can do it ?
and another question what the c.begin() in deque iterator means, i found this exemple :
iterator begin()
{
return this->c.begin();
}
I am not sure, if you selected the correct approach.
Because, you can use a std::deque in the first place. It offers all functionality that a stack offers. And more.
So maybe better use a std::deque or a std::vector.
Additionally, deriving from standard containers is not the best idea. You may read about that here on SO.
But if you want to do that for exceptional purposes, then simply take the address of the top(). This will be the last element in the underlying container. And if you subtract the size() of the stack (corrected by 1), then you have a pointer to the beginning of the underlying container.
And then you can use the artificial iterator and subscript operator [] as expected.
Please see the following example:
#include <vector>
#include <stack>
#include <iostream>
#include <algorithm>
#include <iterator>
using Number = int;
using UnderlyingContainer = std::vector<Number>;
using Stack = std::stack< Number, UnderlyingContainer>;
using StackIterator = Number *const;
int main()
{
// Put the test data onto the stack
Stack myStack{ UnderlyingContainer {1,2,3,4,5} };
if (not myStack.empty()) {
// Get "iterators"
StackIterator end = &myStack.top() + 1;
StackIterator begin = end - myStack.size();
Number *const & stk = begin;
for (size_t i{}; i < myStack.size(); ++i)
stk[i] = stk[i] + 10;
for (size_t i{}; i < myStack.size(); ++i)
std::cout << stk[i] << '\n';
std::transform(begin, end, begin, [](const Number n) {return n - 10; });
std::copy(begin, end, std::ostream_iterator<Number>(std::cout, "\n"));
}
}
So, it looks like we found what you want to have, but in reality, we simply work on the underlying container.
After some research I found this solution:
template <typename T, class container=std::deque<T>>
class MutantStack : public std::stack<T>
{
public:
MutantStack(){}
~MutantStack(){}
MutantStack(const MutantStack &stack)
{
*this = stack;
}
typedef typename container::iterator iterator;
iterator begin()
{
return this->c.begin();
}
iterator end()
{
return this->c.end();
}
};
The stack object inherits from the deque type like this :
template <class Type, class Container = deque<Type> > class stack;
but it exposes only a few methods such as: pop push empty swap and emplace. Therefore it has also the deque iterator. So I used it as above. The c in c.begin() and c.end() is a container_type defined in the stack class:
public:
typedef _Container container_type;
protected:
container_type c;
This means the c is the container and when typing c.begin() we get the first value in Mutantstack; it's like saying value[0] on an array.
Now my MutantStack class inherit from the std::stack class that's itself inherits from the std::deque class:
`MutantStack -> std::stack -> std::deque`
Related
I need to make use of a queue of doubles because of the good properties it has as an ordered container. I want to pass this queue to a class constructor that accepts vectors. If I do that directly I get the following error:
candidate constructor not viable: no known conversion from
'std::queue' to 'std::vector &' for 2nd argument
How to cast a queue to a vector?
The correct container to model both queue_like behaviour and vector-like behaviour is a std::deque.
This has the advantages of:
constant-time insertion and deletion at either end of the deque
ability to iterate elements without destroying the deque
std::deque supports the begin() and end() methods which means you can construct a vector (with compatible value-type) directly.
#include <vector>
#include <deque>
class AcceptsVectors
{
public:
AcceptsVectors(std::vector<double> arg);
};
int main()
{
std::deque<double> myqueue;
auto av = AcceptsVectors({myqueue.begin(), myqueue.end()});
}
A non-mutating conversion of a queue to a vector is not possible.
I don't think there's any direct way available.
Hence this can be achieved by adding elements one by one to the vector.
std::vector<int> v;
while (!q.empty())
{
v.push_back(q.front());
q.pop();
}
Note that the queue will be empty after this.
As suggested by #David in the comment, it'd be good to avoid copying the queue elements (helpful especially when the contained objects are big). Use emplace_back() with std::move() to achieve the same:
v.emplace_back(std::move(q.front()));
std::vector has a constructor taking a pair of iterators, so if you would be able to iterate over the queue, you would be set.
Borrowing from an answer to this question, you can indeed do this by subclassing std::queue:
template<typename T, typename Container=std::deque<T> >
class iterable_queue : public std::queue<T,Container>
{
public:
typedef typename Container::const_iterator const_iterator;
const_iterator begin() const { return this->c.begin(); }
const_iterator end() const { return this->c.end(); }
};
(Note we're allowing only const iteration; for the purpose in the question, we don't need iterators allowing modifying elements.)
With this, it's easy to construct a vector:
#include <queue>
#include <vector>
using namespace std;
template<typename T, typename Container=std::deque<T> >
class iterable_queue : public std::queue<T,Container>
{
public:
typedef typename Container::const_iterator const_iterator;
const_iterator begin() const { return this->c.begin(); }
const_iterator end() const { return this->c.end(); }
};
int main() {
iterable_queue<int> int_queue;
for(int i=0; i<10; ++i)
int_queue.push(i);
vector<int> v(int_queue.begin(), int_queue.end());
return 0;
}
This is just an approach to avoid copying from std::queue to std::vector. I leave it up to you, if to use it or not.
Premises
std::queue is a container adaptor. The internal container by default is std::deque, however you can set it to std::vector as well. The member variable which holds this container is marked as protected luckily. Hence you can hack it by subclassing the queue.
Solution (!)
template<typename T>
struct my_queue : std::queue<T, std::vector<T>>
{
using std::queue<T, std::vector<T>>::queue;
// in G++, the variable name is `c`, but it may or may not differ
std::vector<T>& to_vector () { return this->c; }
};
That's it!!
Usage
my_queue<int> q;
q.push(1);
q.push(2);
std::vector<int>& v = q.to_vector();
Demo.
There are a number of use cases in the standard library, and I have run into my own code, situations where I want to pass an input and an output range that must be the same size, often to some algorithm. At present this requires three, or four if you want to be careful, iterators. Often there is then a bunch of checking to make sure the iterators make sense.
I am aware that array_view might, in some cases, coalesce pairs of being/end iterators but that still leaves checks required that the input and output array_views might be different size. Has there been any discussion on a class to contain both the input and the output range specifications? Maybe the range proposal solves some or all of this of this but I'm not clear how it does.
I often have a similar use case. I have found that the most versatile method is to pass a reference to an output 'container' concept rather than a range or pair of iterators. Then the algorithm is free to resize or extend the container as necessary and the possibility of buffer overruns disappears.
for (a simple contrived) example, something like:
template<class InputIter, class OutputContainer>
void encrypt_to(OutputContainer& dest, InputIter first, InputIter last)
{
dest.resize(last - first);
// ... todo: replace this with some actual encryption
std::copy(first, last, dest.begin());
}
For functions where I want to hide the implementation, I have an abstract interface representing the destination container. It needs virtual begin(), end() and resize() methods.
for example:
#include <iostream>
#include <algorithm>
#include <vector>
struct mutable_byte_buffer_concept {
using iterator=uint8_t*;
virtual iterator begin() = 0;
virtual iterator end() = 0;
virtual void resize(size_t newsize) = 0;
// note : no virtual destructor - by design.
};
template<class Container>
struct mutable_byte_buffer_model : mutable_byte_buffer_concept
{
mutable_byte_buffer_model(Container& container)
: container(container)
{
}
virtual iterator begin() override
{
return reinterpret_cast<iterator>(&container[0]);
}
virtual iterator end() override
{
return reinterpret_cast<iterator>(&container[0]) + container.size();
}
virtual void resize(size_t newsize) override
{
container.resize(newsize);
}
Container& container;
};
template<class Container>
auto make_mutable_buffer(Container& c)
-> mutable_byte_buffer_model<Container>
{
return { c };
}
// note: accepting an rvalue allows me to use polymorphism at the call site without needing any memory allocation
template<class Iter>
void copy_to(mutable_byte_buffer_concept&& dest, Iter first, Iter last)
{
dest.resize(last - first);
std::copy(first, last, dest.begin());
}
using namespace std;
auto main() -> int
{
auto a = "Hello, World"s;
string b;
vector<uint8_t> c;
string d;
copy_to(make_mutable_buffer(b), begin(a), end(a));
copy_to(make_mutable_buffer(c), begin(b), end(b));
copy_to(make_mutable_buffer(d), begin(c), end(c));
cout << d << endl;
return 0;
}
How to store elements in set in insertion order.
for example.
set<string>myset;
myset.insert("stack");
myset.insert("overflow");
If you print, the output is
overflow
stack
needed output :
stack
overflow
One way is to use two containers, a std::deque to store the elements in insertion order, and another std::set to make sure there are no duplicates.
When inserting an element, check if it's in the set first, if yes, throw it out; if it's not there, insert it both in the deque and the set.
One common scenario is to insert all elements first, then process(no more inserting), if this is the case, the set can be freed after the insertion process.
A set is the wrong container for keeping insertion order, it will sort its element according to the sorting criterion and forget the insertion order. You have to use a sequenced container like vector, deque or list for that. If you additionally need the associative access set provides you would have to store your elements in multiple containers simultaneously or use a non-STL container like boost::multi_index which can maintain multiple element orders at the same time.
PS: If you sort the elements before inserting them in a set, the set will keep them in insertion order but I think that will not address your problem.
If you don't need any order besides the insertion order, you could also store the insert number in the stored element and make that the sorting criterion. However, why one would use a set in this case at all escapes me. ;)
Here's how I do it:
template <class T>
class VectorSet
{
public:
using iterator = typename vector<T>::iterator;
using const_iterator = typename vector<T>::const_iterator;
iterator begin() { return theVector.begin(); }
iterator end() { return theVector.end(); }
const_iterator begin() const { return theVector.begin(); }
const_iterator end() const { return theVector.end(); }
const T& front() const { return theVector.front(); }
const T& back() const { return theVector.back(); }
void insert(const T& item) { if (theSet.insert(item).second) theVector.push_back(item); }
size_t count(const T& item) const { return theSet.count(item); }
bool empty() const { return theSet.empty(); }
size_t size() const { return theSet.size(); }
private:
vector<T> theVector;
set<T> theSet;
};
Of course, new forwarding functions can be added as needed, and can be forwarded to whichever of the two data structures implements them most efficiently. If you are going to make heavy use of STL algorithms on this (I haven't needed to so far) you may also want to define member types that the STL expects to find, like value_type and so forth.
If you can use Boost, a very straightforward solution is to use the header-only library Boost.Bimap (bidirectional maps).
Consider the following sample program that will display your dummy entries in insertion order (try out here):
#include <iostream>
#include <string>
#include <type_traits>
#include <boost/bimap.hpp>
using namespace std::string_literals;
template <typename T>
void insertCallOrdered(boost::bimap<T, size_t>& mymap, const T& element) {
// We use size() as index, therefore indexing with 0, 1, ...
// as we add elements to the bimap.
mymap.insert({ element, mymap.size() });
}
int main() {
boost::bimap<std::string, size_t> mymap;
insertCallOrdered(mymap, "stack"s);
insertCallOrdered(mymap, "overflow"s);
// Iterate over right map view (integers) in sorted order
for (const auto& rit : mymap.right) {
std::cout << rit.first << " -> " << rit.second << std::endl;
}
}
I'm just wondering why nobody has suggested using such a nice library as Boost MultiIndex. Here's an example how to do that:
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/indexed_by.hpp>
#include <boost/multi_index/identity.hpp>
#include <boost/multi_index/sequenced_index.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <iostream>
template<typename T>
using my_set = boost::multi_index_container<
T,
boost::multi_index::indexed_by<
boost::multi_index::sequenced<>,
boost::multi_index::ordered_unique<boost::multi_index::identity<T>>
>
>;
int main() {
my_set<int> set;
set.push_back(10);
set.push_back(20);
set.push_back(3);
set.push_back(11);
set.push_back(1);
// Prints elements of the set in order of insertion.
const auto &index = set.get<0>();
for (const auto &item : index) {
std::cout << item << " ";
}
// Prints elements of the set in order of value.
std::cout << "\n";
const auto &ordered_index = set.get<1>();
for (const auto &item : ordered_index) {
std::cout << item << " ";
}
}
what you need is this, very simple and a standard library. Example online compiler link: http://cpp.sh/7hsxo
#include <iostream>
#include <string>
#include <unordered_set>
static std::unordered_set<std::string> myset;
int main()
{
myset.insert("blah");
myset.insert("blah2");
myset.insert("blah3");
int count = 0;
for ( auto local_it = myset.begin(); local_it!= myset.end(); ++local_it ) {
printf("index: [%d]: %s\n", count, (*local_it).c_str());
count++;
}
printf("\n");
for ( unsigned i = 0; i < myset.bucket_count(); ++i) {
for ( auto local_it = myset.begin(i); local_it!= myset.end(i); ++local_it )
printf("bucket: [%d]: %s\n", i, (*local_it).c_str());
}
}
Is there a convenient way to get the index of the current container entry in a C++11 foreach loop, like enumerate in python:
for idx, obj in enumerate(container):
pass
I could imagine an iterator that can also return the index or similar.
Of course I could have a counter, but often iterators don't give guarantees of the order they iterate over a container.
A good implementation of the feature you are requested can be found here:
https://github.com/ignatz/pythonic
The idea behind is, that you build a wrapper struct with a custom iterator that does the counting. Below is a very minimal exemplary implementation to illustrate the idea:
// Distributed under the terms of the GPLv2 or newer
#include <iostream>
#include <vector>
#include <tuple>
// Wrapper class
template <typename T>
class enumerate_impl
{
public:
// The return value of the operator* of the iterator, this
// is what you will get inside of the for loop
struct item
{
size_t index;
typename T::value_type & item;
};
typedef item value_type;
// Custom iterator with minimal interface
struct iterator
{
iterator(typename T::iterator _it, size_t counter=0) :
it(_it), counter(counter)
{}
iterator operator++()
{
return iterator(++it, ++counter);
}
bool operator!=(iterator other)
{
return it != other.it;
}
typename T::iterator::value_type item()
{
return *it;
}
value_type operator*()
{
return value_type{counter, *it};
}
size_t index()
{
return counter;
}
private:
typename T::iterator it;
size_t counter;
};
enumerate_impl(T & t) : container(t) {}
iterator begin()
{
return iterator(container.begin());
}
iterator end()
{
return iterator(container.end());
}
private:
T & container;
};
// A templated free function allows you to create the wrapper class
// conveniently
template <typename T>
enumerate_impl<T> enumerate(T & t)
{
return enumerate_impl<T>(t);
}
int main()
{
std::vector<int> data = {523, 1, 3};
for (auto x : enumerate(data))
{
std::cout << x.index << ": " << x.item << std::endl;
}
}
What about a simple solution like:
int counter=0;
for (auto &val: container)
{
makeStuff(val, counter);
counter++;
}
You could make a bit more "difficult" to add code after the counter by adding a scope:
int counter=0;
for (auto &val: container)
{{
makeStuff(val, counter);
}counter++;}
As #graham.reeds pointed, normal for loop is also a solution, that could be as fast:
int counter=0;
for (auto it=container.begin(); it!=container.end(); ++it, ++counter)
{
makeStuff(val, counter);
}
And finally, a alternative way using algorithm:
int counter = 0;
std::for_each(container.begin(), container.end(), [&counter](int &val){
makeStuff(val, counter++);
});
Note: the order between range loop and normal loop is guaranteed by the standard 6.5.4. Meaning the counter is able to be coherent with the position in the container.
If you have access to Boost its range adaptors can be used like this:
#include <boost/range/adaptor/indexed.hpp>
using namespace boost::adaptors;
for (auto const& elem : container | indexed(0))
{
std::cout << elem.index() << " - " << elem.value() << '\n';
}
Source (where there are also other examples)
C++17 and structured bindings makes this look OK - certainly better than some ugly mutable lambda with a local [i = 0](Element&) mutable or whatever I've done before admitting that probably not everything should be shoehorned into for_each() et al. - and than other solutions that require a counter with scope outside the for loop.
for (auto [it, end, i] = std::tuple{container.cbegin(), container.cend(), 0};
it != end; ++it, ++i)
{
// something that needs both `it` and `i`ndex
}
You could make this generic, if you use this pattern often enough:
template <typename Container>
auto
its_and_idx(Container&& container)
{
using std::begin, std::end;
return std::tuple{begin(container), end(container), 0};
}
// ...
for (auto [it, end, i] = its_and_idx(foo); it != end; ++it, ++i)
{
// something
}
C++ Standard proposal P2164 proposes to add views::enumerate, which would provide a view of a range giving both reference-to-element and index-of-element to a user iterating it.
We propose a view enumerate whose value type is a struct with 2 members index and value representing respectively the position and value of the elements in the adapted range.
[ . . .]
This feature exists in some form in Python, Rust, Go (backed into the language), and in many C++ libraries: ranges-v3, folly, boost::ranges (indexed).
The existence of this feature or lack thereof is the subject of recurring stackoverflow questions.
Hey, look! We're famous.
If you need the index then a traditional for works perfectly well.
for (int idx=0; idx<num; ++idx)
{
// do stuff
}
I'm trying to implement an iterator which encapsulates another iterator and performs range checking. Therefore I'm extending from that Iterator like so:
template<typename ITERATOR_T>
class r_iterator : public ITERATOR_T {
//...
r_iterator (ITERATOR_T begin, ITERATOR_T end) {
this->begin = begin;
this->end = end;
}
};
I want to use the iterators that are passed in the constructor to perform the range checking. My idea is to set the thing to which the "this"-iterator (i.e. r_iterator) points to to the element which is pointed to by the "begin" iterator from the constructor. This I would like to do so I can override certain methods like operator++ for example, perform range checking and then call the super method of the class I'm extending.
I would thus like to know whether it is possible to somehow set the element the "this"-iterator (r_iterator) points to assuming that I'm extending some STL Iterator class.
I could unfortunately not find any information about that in the c++ reference.
Regards and Thank you
There's no need to inherit, you can write a simple wrapper class like this:
#include <iostream>
#include <vector>
#include <stdexcept>
template <typename Iterator>
class MyIterator
{
Iterator _begin;
Iterator _end;
Iterator _cur;
public:
explicit MyIterator(Iterator begin, Iterator end)
: _begin(begin), _end(end)
{
_cur = _begin;
}
bool has_next() const
{
return (_cur != _end);
}
void operator++(int dummy)
{
if (!has_next())
throw std::out_of_range("Out of range.");
_cur++;
}
};
int main(int argc, char* argv[])
{
std::vector<int> v = {1, 2, 3};
MyIterator<std::vector<int>::iterator> my_it(v.begin(), v.end());
my_it++;
my_it++;
my_it++;
my_it++;
return 0;
}