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.
Related
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`
I have an unordered_map that uses a string-type as a key:
std::unordered_map<string, value> map;
A std::hash specialization is provided for string, as well as a
suitable operator==.
Now I also have a "string view" class, which is a weak pointer into an existing string, avoiding heap allocations:
class string_view {
string *data;
size_t begin, len;
// ...
};
Now I'd like to be able to check if a key exists in the map using a string_view object. Unfortunately, std::unordered_map::find takes a Key argument, not a generic T argument.
(Sure, I can "promote" one to a string, but that causes an allocation I'd like to avoid.)
What I would've liked instead was something like
template<class Key, class Value>
class unordered_map
{
template<class T> iterator find(const T &t);
};
which would require operator==(T, Key) and std::hash<T>() to be suitably defined, and would return an iterator to a matching value.
Is there any workaround?
P0919R2 Heterogeneous lookup for unordered containers has been merged in the C++2a's working draft!
The abstract seems a perfect match w.r.t. my original question :-)
Abstract
This proposal adds heterogeneous lookup support to the unordered associative containers in the C++ Standard Library. As a result, a creation of a temporary key object is not needed when different (but compatible) type is provided as a key to the member function. This also makes unordered and regular associative container interfaces and functionality more compatible with each other.
With the changes proposed by this paper the following code will work without any additional performance hits:
template<typename Key, typename Value>
using h_str_umap = std::unordered_map<Key, Value, string_hash>;
h_str_umap<std::string, int> map = /* ... */;
map.find("This does not create a temporary std::string object :-)"sv);
As mentioned above, C++14 does not provide heterogeneous lookup for std::unordered_map (unlike std::map). You can use Boost.MultiIndex to define a fairly close substitute for std::unordered_map that allows you to look up string_views without allocating temporary std::strings:
Live Coliru Demo
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/hashed_index.hpp>
#include <boost/multi_index/member.hpp>
#include <string>
using namespace boost::multi_index;
struct string_view
{
std::string *data;
std::size_t begin,len;
};
template<typename T,typename Q>
struct mutable_pair
{
T first;
mutable Q second;
};
struct string_view_hash
{
std::size_t operator()(const string_view& v)const
{
return boost::hash_range(
v.data->begin()+v.begin,v.data->begin()+v.begin+v.len);
}
std::size_t operator()(const std::string& s)const
{
return boost::hash_range(s.begin(),s.end());
}
};
struct string_view_equal_to
{
std::size_t operator()(const std::string& s1,const std::string& s2)const
{
return s1==s2;
}
std::size_t operator()(const std::string& s1,const string_view& v2)const
{
return s1.size()==v2.len&&
std::equal(
s1.begin(),s1.end(),
v2.data->begin()+v2.begin);
}
std::size_t operator()(const string_view& v1,const std::string& s2)const
{
return v1.len==s2.size()&&
std::equal(
v1.data->begin()+v1.begin,v1.data->begin()+v1.begin+v1.len,
s2.begin());
}
};
template<typename Q>
using unordered_string_map=multi_index_container<
mutable_pair<std::string,Q>,
indexed_by<
hashed_unique<
member<
mutable_pair<std::string,Q>,
std::string,
&mutable_pair<std::string,Q>::first
>,
string_view_hash,
string_view_equal_to
>
>
>;
#include <iostream>
int main()
{
unordered_string_map<int> m={{"hello",0},{"boost",1},{"bye",2}};
std::string str="helloboost";
auto it=m.find(string_view{&str,5,5});
std::cout<<it->first<<","<<it->second<<"\n";
}
Output
boost,1
I faced an equal problem.
We need two structs:
struct string_equal {
using is_transparent = std::true_type ;
bool operator()(std::string_view l, std::string_view r) const noexcept
{
return l == r;
}
};
struct string_hash {
using is_transparent = std::true_type ;
auto operator()(std::string_view str) const noexcept {
return std::hash<std::string_view>()(str);
}
};
For unordered_map:
template <typename Value>
using string_unorderd_map = std::unordered_map<std::string, Value, string_hash, string_equal>;
For unordered_set:
using string_unorderd_set = std::unordered_set<std::string, string_hash, string_equal>;
Now using string_view is possible.
It looks like only as recently as C++14 did even the basic map get such a templated find for is_transparent types in the comparison. Most likely the correct implementation for hashed containers was not immediately evident.
As far as I can see your two options are:
Just do the allocation and profile to see if maybe it's not actually a problem.
Take a look at boost::multi_index (http://www.boost.org/doc/libs/1_60_0/libs/multi_index/doc/index.html) and have both string and string_view indexes into the container.
This solution has drawbacks, which may or may not make it unviable for your context.
You can make a wrapper class:
struct str_wrapper {
const char* start, end;
};
And change your map to use str_wrapper as its key. You'd have to add 2 constructors to str_wrapper, one for std::string and one for your string_view. The major decision is whether to make these constructors perform deep or shallow copies.
For example, if you use std::string only for inserts and str_view only for lookups, you'd make the std::string constructor deep and the str_view one shallow (this can be enforced at compile time if you use a custom wrapper around unordered_map). If you care to avoid memory leaks on the deep copy you would need additional fields to support proper destruction.
If your usage is more varied, (looking up std::string's or inserting by str_view), there will be drawbacks, which again, might make the approach too distasteful so as to be unviable. It depends on your intended usage.
Yet another option is to split the lookup and the data management by using multiple containters:
std::unordered_map<string_view, value> map;
std::vector<unique_ptr<const char[]>> mapKeyStore;
Lookups are done using string_views without the need of allocations.
Whenever a new key is inserted we need to add a real string allocation first:
mapKeyStore.push_back(conv(str)); // str can be string_view, char*, string... as long as it converts to unique_ptr<const char[]> or whatever type
map.emplace(mapKeyStore.back().get(), value)
It would be much more intuitive to use std::string in the mapKeyStore. However, using std::string does not guarantee unchanging string memory (e.g. if the vector resizes). With the unique_ptr this is enforced. However, we need some special conversion/allocation routine, called conv in the example. If you have a custom string container which guarantees data consistency under moves (and forces the vector to use moves), then you can use it here.
The drawback
The disadvantage of the above method is that handling deletions is non-trivial and expensive if done naive. If the map is only created once or only growing this is a non-issue and the above pattern works quite well.
Running example
The below example includes a naive deletion of one key.
#include <vector>
#include <unordered_map>
#include <string>
#include <string_view>
#include <iostream>
#include <memory>
#include <algorithm>
using namespace std;
using PayLoad = int;
unique_ptr<const char[]> conv(string_view str) {
unique_ptr<char[]> p (new char [str.size()+1]);
memcpy(p.get(), str.data(), str.size()+1);
return move(p);
}
int main() {
unordered_map<string_view, PayLoad> map;
vector<unique_ptr<const char[]>> mapKeyStore;
// Add multiple values
mapKeyStore.push_back(conv("a"));
map.emplace(mapKeyStore.back().get(), 3);
mapKeyStore.push_back(conv("b"));
map.emplace(mapKeyStore.back().get(), 1);
mapKeyStore.push_back(conv("c"));
map.emplace(mapKeyStore.back().get(), 4);
// Search all keys
cout << map.find("a")->second;
cout << map.find("b")->second;
cout << map.find("c")->second;
// Delete the "a" key
map.erase("a");
mapKeyStore.erase(remove_if(mapKeyStore.begin(), mapKeyStore.end(),
[](const auto& a){ return strcmp(a.get(), "a") == 0; }),
mapKeyStore.end());
// Test if verything is OK.
cout << '\n';
for(auto it : map)
cout << it.first << ": " << it.second << "\n";
return 0;
}
Of course, the two containers can be put into a wrapper which handles the insertion and deletion for its own.
I'll just present one variation I found on github, it involves defining a new map class that wraps the std.
Redefining some key API to intercept the adaptors we want, and use a static string to copy the key.
It's not necessary a good solution, but it's interesting to know it exists for people who deems it enough.
original:
https://gist.github.com/facontidavide/95f20c28df8ec91729f9d8ab01e7d2df
code gist:
template <typename Value>
class StringMap: public std::unordered_map<std::string, Value>
{
public:
typename std::unordered_map<string,Value>::iterator find(const nonstd::string_view& v )
{
tmp_.reserve( v.size() );
tmp_.assign( v.data(), v.size() );
return std::unordered_map<string, Value>::find(tmp_);
}
typename std::unordered_map<std::string,Value>::iterator find(const std::string& v )
{
return std::unordered_map<std::string, Value>::find(v);
}
typename std::unordered_map<std::string,Value>::iterator find(const char* v )
{
tmp_.assign(v);
return std::unordered_map<std::string, Value>::find(v);
}
private:
thread_local static std::string tmp_;
};
credits:
Davide Faconti
Sorry for answering this very old question, but it still comes up in search engine results...
In this case your unordered_map is using the string type as its key, the find method is looking for a reference to a string which will not generate an allocation. Your string_view class stores a pointer to a string. Therefore your string_view class can dereference the pointer into a ref of the type needed for your map without causing an allocation. The method would look like this...
string &string_view::getRef() const
{
return *_ptr;
}
and to use the string_view with the map it would look like this
auto found=map.find(string_view_inst.getRef());
note that this will not work for the c++17 string_view class as it does not internally store a std::string object
ps.
Your string_view class is probably not great for cpu caches as it stores a pointer to a string allocated somewhere on the heap, and the string itself stores a pointer to the actual data located somewhere else on the heap. Every time you access your string_view it will result in a double dereference.
You could allow your view to be implicitly convertible to a std::string:
class StringView {
// ...
operator std::string() const
{
return data->substr(begin, len);
}
// ...
};
Let's say I have a private variable which is a vector of shared_ptrs to non-const objects.
Is it possible to write a getter method which only allows read access to the data pointed to by the shared pointers?
I want to be able to use range-based loops for elegance, so I want to avoid writing const_iterators.
My understanding is that const shared_ptr<T> makes the pointer itself const, not T. I tried to compile shared_ptr<const T>, but it doesn't compile if T itself is not declared const in the class.
In other words, how could I write something like:
#include <iostream>
#include <vector>
#include <memory>
using std::vector;
using std::shared_ptr;
using std::make_shared;
using std::cout;
using std::endl;
class MyClass{
public:
MyClass(int element1, int element2)
{
myVector_.push_back(std::make_shared<int>(element1));
myVector_.push_back(std::make_shared<int>(element2));
}
// I want something like this, but doesn't compile
// const vector<shared_ptr<const int>> readMyVector() const {return myVector_;}
const vector<shared_ptr<int>> readMyVector() const {return myVector_;}
private:
// Should NOT be <const int>, the class should be able to modify its elements
vector<shared_ptr<int>> myVector_;
};
int main(){
auto testobject = MyClass(1,2);
for (auto my_protected_data : testobject.readMyVector()){
cout<<(*my_protected_data)<<endl;
(*my_protected_data) = 25;
cout<<(*my_protected_data)<<endl; // Should not happen
}
return 0;
}
The correct type to return is std::vector<std::shared_ptr<const int>>, but you'll have to make that vector by hand. std::shared_ptr<T> is convertible to std::shared_ptr<const T>, but the problem is that std::vector<T> isn't implicitly convertible to std::vector<U> simply because T is convertible to U.
The easiest way is to construct a vector from your internal vector's begin and end iterators.
vector<shared_ptr<const int>> readMyVector() const
{
return{ myVector_.begin(), myVector_.end() };
}
Note that adding const to the return type of a function that returns by value is rarely useful.
You should also ask yourself rather it's worth it to copy all of those std::shared_ptr. You may want to consider simply returning a vector of int.
If you want to make your getter to return vector of shared pointers to const data, there is only one way, to return copy of shared pointers to const data.
const vector<shared_ptr<const int>> readMyVector() const
{
vector<shared_ptr<const int>> cdata(myVector_.begin(), myVector_.end());
return cdata;
}
std::vector, std::list and std::deque have std::back_inserter, and std::set has std::inserter.
For std::stack and std::priority_queue I would assume the equivalent inserter would be a push() but I can't seem to find the correct function to call.
My intent is to be able to use the following function with the correct insert iterator:
#include <string>
#include <queue>
#include <iterator>
template<typename outiter>
void foo(outiter oitr)
{
static const std::string s1 ("abcdefghji");
static const std::string s2 ("1234567890");
*oitr++ = s1;
*oitr++ = s2;
}
int main()
{
std::priority_queue<std::string> spq;
std::stack<std::string> stk;
foo(std::inserter(spq));
foo(std::inserter(stk));
return 0;
}
The other alternative (simpler) is just to use the underlying data structure (std::stack is usually implemented using std::deque) and accept that you have to use e.g. push_back() instead of push(). Saves having to code your own iterator, and doesn't particularly affect the clarity of the code. std::stack isn't your only choice for modelling the stack concept.
You can always go your own way and implement an iterator yourself. I haven't verified this code but it should work. Emphasis on "I haven't verified."
template <class Container>
class push_insert_iterator:
public iterator<output_iterator_tag,void,void,void,void>
{
protected:
Container* container;
public:
typedef Container container_type;
explicit push_insert_iterator(Container& x) : container(&x) {}
push_insert_iterator<Container>& operator= (typename Container::const_reference value){
container->push(value); return *this; }
push_insert_iterator<Container>& operator* (){ return *this; }
push_insert_iterator<Container>& operator++ (){ return *this; }
push_insert_iterator<Container> operator++ (int){ return *this; }
};
I'd also add in the following function to help use it:
template<typename Container>
push_insert_iterator<Container> push_inserter(Container container){
return push_insert_iterator<Container>(container);
}
I'm writing some C++ code that manipulates a bunch of vectors that are changing in size and are thus being reallocated constantly.
I would like to get a "pointer" into these vectors that remains valid even after reallocation of the vector. More specifically, I just want these "pointers" to remember which vector they point into and the index to which they point. When I dereference them using the standard (*ptr) syntax, I just want them to do the obvious lookup.
Obviously, actual pointers will not be valid after reallocation, and my understanding is that iterators aren't valid after reallocation either. Note also that I don't care if elements are inserted before my objects, so these "pointers" really don't have to remember anything but a vector and an index.
Now, I could easily write such a class myself. Has anyone (Boost? STL?) done it for me already?
Edit: The answers don't address my question. I asked if this functionality is any standard library. I take the responses as a "no"?
Try a std::pair< vector*, int>, as neither the position of the vector nor the index of the element changes.
Or, as a class:
template<class T> class VectorElementPointer
{
vector<T>& vectorref;
typename vector<T>::size_type index;
public:
VectorElementPointer(vector<T>& vref, typename vector<T>::size_type index):vectorref(vref),index(index){}
T& operator*() const {return vectorref[index];}
T* operator->() const {return &vectorref[index];}
};
This is the easiest solution that comes to my mind, as neither the STL nor Boost contains anything to do it easier.
An article on persistent iterators, complete with implementation.
To summarize some ideas. Here is the minimalist wrapper that tries to mimic iterators but stay valid as opposite to vector's ones.
void print(const std::string& i)
{
std::cout << "<" << i << "> ";
}
int main()
{
typedef std::vector<std::string> Vector;
Vector v;
v.push_back("H");
v.push_back("E");
v.push_back("W");
StrongIterator<Vector> it0(v, 0);
StrongIterator<Vector> it3(v, v.end());
std::for_each(it0.it(), it3.it(), print);
std::cout << std::endl;
v.push_back("O");
std::for_each(it0.it(), it3.it(), print);
std::cout << *it0;
std::cout << it0->c_str();
return 0;
}
And the iterator itself.
template <typename TVector>
class StrongIterator
{
public:
typedef typename TVector::iterator iterator;
typedef typename TVector::size_type size_type;
typedef typename TVector::value_type value_type;
StrongIterator(TVector& vector,
size_type index):
vector_(vector),
index_(index)
{}
StrongIterator(TVector& vector,
iterator it):
vector_(vector),
index_(std::distance(vector.begin(), it))
{}
iterator it()
{
iterator it = vector_.begin();
std::advance(it, index_);
return it;
}
value_type& operator*()
{
return vector_[index_];
}
value_type* operator->()
{
return &vector_[index_];
}
private:
TVector& vector_;
size_type index_;
};
Unfortunately, once you modify the vector, the iterators that would "point" to an element of the vector are no longer guaranteed to be valid. The only STL structure that I know of which will keep the iterators valid even as the structure is changing is the list<>. If you only want sequential iteration of your structures than you can use std::list<> otherwise I do not know of any other library that can help you; that doesn't mean there isn't one.
Here's some clear documentation on std::list : http://www.cplusplus.com/reference/stl/list/
Using boost::iterator_facade :
// Warning: Untested, not even compiled
template<class VectorT>
class VectorIndex :
public boost::iterator_facade<VectorIndex, typename VectorT::reference, boost::random_access_traversal_tag>
{
public:
VectorIndex(VectorT& Vec, typename VectorT::size_type Index)
: m_Vec(Vec), m_Index(Index)
{
}
private:
friend class boost::iterator_core_access;
void increment()
{
++m_Index;
}
void decrement()
{
--m_Index;
}
void advance(difference_type N)
{
m_Index += N;
}
difference_type distance_to(const VectorIndex& Other)
{
assert(&this->m_Vec == &Other.m_Vec);
return Other.m_Index = this->m_Index;
}
bool equal(const VectorIndex& Other)const
{
return (this->m_Vec == Other.m_Vec)
&& (this->m_Index == Other.m_Index);
}
VectorT::reference dereference() const
{
return m_Vec[m_Index];
}
VectorT m_Vec;
VectorT::size_type m_Index;
};
Unless you write your own version of vector and smart pointer there is no way that a pointer will be valid after a reallocation. If you had your own implementations the smart vector could send notifications to your smart pointers.
However I think that the whole scenario is a bad design and you might be better of redesigning your scenario so that you don't have a requirement like that.
Depending on your use pattern, a std::deque may fufil your requirements. Pointers into a deque are only invalidated if you insert or delete items not at the beginning or end - in pother words push_front() and push_back() don't invalidate pointers into the deque, but other changes do. You get basically the same interface as a vector, but of course the underlying storage is not contiguous.