Inserters for STL stack and priority_queue - c++

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);
}

Related

Recasting a container of void pointers

Short version
Can I reinterpret_cast a std::vector<void*>* to a std::vector<double*>*?
What about with other STL containers?
Long version
I have a function to recast a vector of void pointers to a datatype specified by a template argument:
template <typename T>
std::vector<T*> recastPtrs(std::vector<void*> const& x) {
std::vector<T*> y(x.size());
std::transform(x.begin(), x.end(), y.begin(),
[](void *a) { return static_cast<T*>(a); } );
return y;
}
But I was thinking that copying the vector contents isn't really necessary, since we're really just reinterpreting what's being pointed to.
After some tinkering, I came up with this:
template <typename T>
std::vector<T*> recastPtrs(std::vector<void*>&& x) {
auto xPtr = reinterpret_cast<std::vector<T*>*>(&x);
return std::vector<T*>(std::move(*xPtr));
}
So my questions are:
Is it safe to reinterpret_cast an entire vector like this?
What if it was a different kind of container (like a std::list or std::map)? To be clear, I mean casting a std::list<void*> to std::list<T*>, not casting between STL container types.
I'm still trying to wrap my head around move semantics. Am I doing it right?
And one follow-up question: What would be the best way to generate a const version without code duplication? i.e. to define
std::vector<T const*> recastPtrs(std::vector<void const*> const&);
std::vector<T const*> recastPtrs(std::vector<void const*>&&);
MWE
#include <vector>
#include <algorithm>
#include <iostream>
template <typename T>
std::vector<T*> recastPtrs(std::vector<void*> const& x) {
std::vector<T*> y(x.size());
std::transform(x.begin(), x.end(), y.begin(),
[](void *a) { return static_cast<T*>(a); } );
return y;
}
template <typename T>
std::vector<T*> recastPtrs(std::vector<void*>&& x) {
auto xPtr = reinterpret_cast<std::vector<T*>*>(&x);
return std::vector<T*>(std::move(*xPtr));
}
template <typename T>
void printVectorAddr(std::vector<T> const& vec) {
std::cout<<" vector object at "<<&vec<<", data()="<<vec.data()<<std::endl;
}
int main(void) {
std::cout<<"Original void pointers"<<std::endl;
std::vector<void*> voidPtrs(100);
printVectorAddr(voidPtrs);
std::cout<<"Elementwise static_cast"<<std::endl;
auto dblPtrs = recastPtrs<double>(voidPtrs);
printVectorAddr(dblPtrs);
std::cout<<"reintepret_cast entire vector, then move ctor"<<std::endl;
auto dblPtrs2 = recastPtrs<double>(std::move(voidPtrs));
printVectorAddr(dblPtrs2);
}
Example output:
Original void pointers
vector object at 0x7ffe230b1cb0, data()=0x21de030
Elementwise static_cast
vector object at 0x7ffe230b1cd0, data()=0x21de360
reintepret_cast entire vector, then move ctor
vector object at 0x7ffe230b1cf0, data()=0x21de030
Note that the reinterpret_cast version reuses the underlying data structure.
Previously-asked questions that didn't seem relevant
These are the questions that come up when I tried to search this:
reinterpret_cast vector of class A to vector of class B
reinterpret_cast vector of derived class to vector of base class
reinterpret_cast-ing vector of one type to a vector of another type which is of the same type
And the answer to these was a unanimous NO, with reference to the strict aliasing rule. But I figure that doesn't apply to my case, since the vector being recast is an rvalue, so there's no opportunity for aliasing.
Why I'm trying to do this
I'm interfacing with a MATLAB library that gives me data pointers as void* along with a variable indicating the datatype. I have one function that validates the inputs and collects these pointers into a vector:
void parseInputs(int argc, mxArray* inputs[], std::vector<void*> &dataPtrs, mxClassID &numericType);
I can't templatize this part since the type is not known until runtime. On the other side, I have numeric routines to operate on vectors of a known datatype:
template <typename T>
void processData(std::vector<T*> const& dataPtrs);
So I'm just trying to connect one to the other:
void processData(std::vector<void*>&& voidPtrs, mxClassID numericType) {
switch (numericType) {
case mxDOUBLE_CLASS:
processData(recastPtrs<double>(std::move(voidPtrs)));
break;
case mxSINGLE_CLASS:
processData(recastPtrs<float>(std::move(voidPtrs)));
break;
default:
assert(0 && "Unsupported datatype");
break;
}
}
Given the comment that you're receiving the void * from a C library (something like malloc), it seems like we can probably narrow the problem down quite a bit.
In particular, I'd guess you're really dealing with something that's more like an array_view than a vector. That is, you want something that lets you access some data cleanly. You might change individual items in that collection, but you'll never change the collection as a whole (e.g., you won't try to do a push_back that could need to expand the memory allocation).
For such a case, you can pretty easily create a wrapper of your own that gives you vector-like access to the data--defines an iterator type, has a begin() and end() (and if you want, the others like rbegin()/rend(), cbegin()/cend() and crbegin()/crend()), as well as an at() that does range-checked indexing, and so on.
So a fairly minimal version could look something like this:
#pragma once
#include <cstddef>
#include <stdexcept>
#include <cstdlib>
#include <iterator>
template <class T> // note: no allocator, since we don't do allocation
class array_view {
T *data;
std::size_t size_;
public:
array_view(void *data, std::size_t size_) : data(reinterpret_cast<T *>(data)), size_(size_) {}
T &operator[](std::size_t index) { return data[index]; }
T &at(std::size_t index) {
if (index > size_) throw std::out_of_range("Index out of range");
return data[index];
}
std::size_t size() const { return size_; }
typedef T *iterator;
typedef T const &const_iterator;
typedef T value_type;
typedef T &reference;
iterator begin() { return data; }
iterator end() { return data + size_; }
const_iterator cbegin() { return data; }
const_iterator cend() { return data + size_; }
class reverse_iterator {
T *it;
public:
reverse_iterator(T *it) : it(it) {}
using iterator_category = std::random_access_iterator_tag;
using difference_type = std::ptrdiff_t;
using value_type = T;
using pointer = T *;
using reference = T &;
reverse_iterator &operator++() {
--it;
return *this;
}
reverse_iterator &operator--() {
++it;
return *this;
}
reverse_iterator operator+(size_t size) const {
return reverse_iterator(it - size);
}
reverse_iterator operator-(size_t size) const {
return reverse_iterator(it + size);
}
difference_type operator-(reverse_iterator const &r) const {
return it - r.it;
}
bool operator==(reverse_iterator const &r) const { return it == r.it; }
bool operator!=(reverse_iterator const &r) const { return it != r.it; }
bool operator<(reverse_iterator const &r) const { return std::less<T*>(r.it, it); }
bool operator>(reverse_iterator const &r) const { return std::less<T*>(it, r.it); }
T &operator *() { return *(it-1); }
};
reverse_iterator rbegin() { return data + size_; }
reverse_iterator rend() { return data; }
};
I've tried to show enough that it should be fairly apparent how to add most of the missing functionality (e.g., crbegin()/crend()), but I haven't worked really hard at including everything here, since much of what's left is more repetitive and tedious than educational.
This is enough to use the array_view in most of the typical vector-like ways. For example:
#include "array_view"
#include <iostream>
#include <iterator>
int main() {
void *raw = malloc(16 * sizeof(int));
array_view<int> data(raw, 16);
std::cout << "Range based:\n";
for (auto & i : data)
i = rand();
for (auto const &i : data)
std::cout << i << '\n';
std::cout << "\niterator-based, reverse:\n";
auto end = data.rend();
for (auto d = data.rbegin(); d != end; ++d)
std::cout << *d << '\n';
std::cout << "Forward, counted:\n";
for (int i=0; i<data.size(); i++) {
data[i] += 10;
std::cout << data[i] << '\n';
}
}
Note that this doesn't attempt to deal with copy/move construction at all, nor with destruction. At least as I've formulated it, the array_view is a non-owning view into some existing data. It's up to you (or at least something outside of the array_view) to destroy the data when appropriate. Since we're not destroying the data, we can use the compiler-generated copy and move constructors without any problem. We won't get a double-delete from doing a shallow copy of the pointer, because we don't do any delete when the array_view is destroyed.
No, you cannot do anything like this in Standard C++.
The strict aliasing rule says that to access an object of type T, you must use an expression of type T; with a very short list of exceptions to that.
Accessing a double * via a void * expression is not such an exception; let alone a vector of each. Nor is it an exception if you accessed the object of type T via an rvalue.

how to trivially adapt set or map ordering predicate for pointers

There must be a trivial answer to this...
I have a std::set or a std::map or some object type which has a natural ordering - say std::less.
I need to change my set or map to contain shared_ptr instead of copies of T.
So I want something like:
using my_set std::set<std::shared_ptr<T>, std::less<*T>>;
But I'm drawing a blank as to how to specify "use the less adaptor on ____ adaptor of T so that it's on dereferenced members, not on shared_ptrs!"
Is there a std::less<std::dereference<std::shared_ptr<T>>> equivalent?
There is currently no functor in the C++ standard library to achieve what you want. You can either write a custom comparator, or if you need this functionality often, come up with an indirect/dereference function object.
Related and potentially helpful threads; the first one offers a generic solution for many operators (even if it requires a bit of code):
Why do several of the standard operators not have standard functors?
Functor that calls a function after dereferencing?
Less-than function dereferencing pointers
While the standard library may not already provide what you need, I think it's pretty trivial to write your own std::dereference_less:
#include <memory>
#include <set>
namespace std
{
template<typename T>
struct dereference_less
{
constexpr bool operator ()(const T& _lhs, const T& _rhs) const
{
return *_lhs < *_rhs;
}
};
}
int main()
{
using key_type = std::shared_ptr<int>;
std::set<key_type, std::dereference_less<key_type>> mySet;
}
Demo (refactored a bit to have a template type alias like in your question)
Since you are already changing your internal interface to something that requires dereferencing you could also just write a wrapper class and provide a bool operator< () as follows:
#include <memory> // shared_ptr
#include <set> // set
#include <iostream> // cout
using namespace std;
template<typename T>
class wrapper
{
public:
shared_ptr<T> sp;
bool operator< (const wrapper<T>& rhs) const
{
return *( sp.get() ) < *( rhs.sp.get() ) ;
}
wrapper(){}
wrapper(shared_ptr<T> sp):sp(sp){}
};
int main()
{
shared_ptr<int> sp1 (new int);
*sp1 = 1;
shared_ptr<int> sp2 (new int);
*sp2 = 2;
set<wrapper<int>> S;
S.insert(wrapper<int>(sp2));
S.insert(wrapper<int>(sp1));
for (auto& j : S)
cout << *(j.sp) << endl;
return 0;
}

How to convert std::queue to std::vector

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.

Specifying input and output ranges to algorithms

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;
}

Extend std::vector to move elements from other vector type

Let's assume I have a non-STL vector type that is compatible with std::vector by an operator std::vector<T>. Is it possible to move its elements to a std::vector instead of the default copy construction, so that
OtherVectorType<SomeClass> f()
{
OtherVectorType<SomeClass> v;
v.pushBack(SomeClass());
v.pushBack(SomeClass());
v.pushBack(SomeClass());
return v;
}
std::vector<SomeClass> sv = f();
would use SomeClass's move constructor (3 times) when creating the std::vector sv?
I imagine something like
template<typename T>
std::vector<T>& operator= (std::vector<T>& self, OtherVectorType<T>&& from)
{
[...]
}
but haven't found any working solution yet.
For illustration, this is how the std::vector operator is defined:
template<typename T> class OtherVectorType
{
[...]
operator std::vector<T>() const
{
if (!m_size)
return std::vector<T>();
return std::vector<T>(reinterpret_cast<T*>(m_pElements),
reinterpret_cast<T*>(m_pElements) + m_size);
}
}
I think you need support for rvalue references for *this.
operator std::vector<T>() const &; // copy your own type's data
operator std::vector<T>() &&; // move it into the std::vector<T>
Sadly, support is rare, even GCC 4.8 does not have it. :(
The easiest thing to do (especially if you don't have rvalue-this) is to make use of make_move_iterator as demonstrated below:
#include <deque>
#include <vector>
#include <memory>
#include <iterator>
typedef std::unique_ptr<int> SomeClass;
typedef std::deque<SomeClass> OtherVectorType;
OtherVectorType
f()
{
OtherVectorType v;
v.push_back(SomeClass(new int (1)));
v.push_back(SomeClass(new int (2)));
v.push_back(SomeClass(new int (3)));
return v;
}
std::vector<SomeClass>
to_vector(OtherVectorType&& o)
{
return std::vector<SomeClass>(std::make_move_iterator(o.begin()),
std::make_move_iterator(o.end()));
}
int main()
{
std::vector<SomeClass> v = to_vector(f());
}