I was wondering if there is an iterator in the STL that dereferences the object pointed before returning it. This could be very useful when manipulating containers aggregating pointers. Here's an example of what I would like to be able to do:
#include <vector>
#include <iterator>
#include <algorithm>
using namespace std;
int main()
{
vector<int*> vec;
int i = 1;
int j = 2;
int k = 3;
vec.push_back(&i);
vec.push_back(&j);
vec.push_back(&k);
copy(deref_iterator(vec.begin()),
deref_iterator(vec.end()),
ostream_iterator<int>(cout, " ")); // prints "1 2 3"
return 0;
}
Try Boost's indirect_iterator.
An indirect_iterator has the same category as the iterator it is wrapping. For example, an indirect_iterator<int**> is a random access iterator.
Assuming your actual use case is a bit more complex than a container of integer pointers!
You could check out the boost ptr containers
http://www.boost.org/doc/libs/1_35_0/libs/ptr_container/doc/reference.html
The containers contain dynamically allocated objects (ie pointers).
But all access to the objects (direct or via iterator) returns a reference to the object.
#include <boost/ptr_container/ptr_vector.hpp>
#include <iostream>
#include <iterator>
#include <algorithm>
using namespace std;
int main()
{
boost::ptr_vector<int> vec;
vec.push_back(new int(1));
vec.push_back(new int(2));
vec.push_back(new int(3));
copy(vec.begin(),vec.end(),
ostream_iterator<int>(std::cout, " ")); // prints "1 2 3 "
return 0;
}
If it is impossible using Boost, writing a custom iterator is not that hard. Here is an example of a "dereference iterator" that meets the InputIterator requirements :
#include <iterator>
template <typename T>
struct PointedType;
template <typename T>
struct PointedType<T*>
{
typedef T value_type;
};
template <typename InputIterator>
struct DerefIterator
{
typedef input_iterator_tag iterator_category;
typedef typename PointedType<
typename iterator_traits<InputIterator>::value_type>::value_type
value_type;
typedef typename iterator_traits<InputIterator>::difference_type
difference_type;
typedef value_type* pointer;
typedef value_type& reference;
public:
explicit DerefIterator(const InputIterator& ii)
: it(ii) {}
// Returns the object pointed by the object referenced by it
reference operator*() const { return **it; }
pointer operator->() const { return *it; }
DerefIterator& operator++()
{
++it;
return *this;
}
DerefIterator operator++(int)
{
DerefIterator tmp = *this;
++it;
return tmp;
}
bool equals(const DerefIterator<InputIterator> & di) const
{
return di.it == it;
}
private:
InputIterator it;
};
// Equality functions
template <typename InputIterator>
inline bool operator==(const DerefIterator<InputIterator>& di1,
const DerefIterator<InputIterator>& di2)
{
return di1.equals(di2);
}
template <typename InputIterator>
inline bool operator!=(const DerefIterator<InputIterator>& di1,
const DerefIterator<InputIterator>& di2)
{
return ! (di1 == di2);
}
//Helper function
template <typename InputIterator>
DerefIterator<InputIterator> deref_iterator(const InputIterator& ii)
{
return DerefIterator<InputIterator>(ii);
}
Related
I'm trying to write a wrapper class that interprets a std::vector<T> as a mapping of integers to Ts. As I want it to behave like a map, its iterators should dereference to (key, value) pairs. Since there are no such pairs in memory, the reference type of my corresponding iterator class is a bit unconventional:
using value_type = std::pair<Key, Value>;
using reference = std::pair<Key, Value&>;
For the corresponding const_iterator, this becomes
using value_type = std::pair<Key, const Value>;
using reference = std::pair<Key, const Value&>;
Now, however, my const_iterator no longer satisfies std::indirectly_readable (and, thus, std::forward_iterator and, thus, std::random_access_iterator) because
no type named 'type' in 'struct std::common_reference<std::pair<long unsigned int, const int&>&&, std::pair<long unsigned int, const int>&>'
(see https://godbolt.org/z/s89z56rY7) or the full code here:
#include <iostream>
#include <type_traits>
#include <vector>
#include <iterator>
using namespace std;
template<class Value, class VType, class RType>
struct _vector_map_iterator {
Value* _data = nullptr;
size_t index = 0;
using value_type = VType;
using reference = RType;
using difference_type = ptrdiff_t;
using iterator_category = std::random_access_iterator_tag;
reference operator*() const { return {index, *_data}; }
_vector_map_iterator& operator++() { ++index; return *this; }
_vector_map_iterator operator++(int) {_vector_map_iterator res = *this; ++(*this); return res; }
bool operator==(const _vector_map_iterator& other) const { return _data == other.data; }
};
template<class T>
using vmap_iterator = _vector_map_iterator<T, pair<size_t, T>, pair<size_t, T&>>;
template<class T>
using vmap_const_iterator = _vector_map_iterator<const T, pair<size_t, const T>, pair<size_t, const T&>>;
using I = vmap_const_iterator<int>;
//static_assert(std::common_reference_with<typename I::reference&&, typename I::value_type&>);
static_assert(forward_iterator<I>);
template<class Value>
struct vector_map {
vector<Value> _raw_data;
using iterator = vmap_iterator<Value>;
using const_iterator = vmap_const_iterator<Value>;
iterator begin() { return {_raw_data.data(), 0}; }
const_iterator begin() const { return {_raw_data.data(), 0}; }
vector_map(const initializer_list<Value>& lst): _raw_data(lst) {};
};
int main(){
const vector_map<int> int_map = {1,2,3};
const auto it = int_map.begin();
cout << (*it).first << ": " << (*it).second << '\n';
}
My question would be: is there a sensible (I specifically do not want to store key-value-pairs in the vector!) design for such an iterator class that also adheres to std::random_access_iterator?
EDIT: more details + full example
Suppose I have a nested structure, say some class that contains some other classes:
struct Obj
{
std::vector<T> mVector; // T is large
};
std::vector<Obj> myVector;
I want to use some existing function, let's call it std::find_if, to find occurrences of T that match some criterion, etc. Many Standard Library functions (std::find_if included) require iterable ranges as inputs, so simply passing myVector iterators into these functions will cause the rows, not the elements, to be traversed.
Performance is also a concern so I don't want to have to reconstruct an entire vector of pointers or, worse, copy the objects themselves just in order to run these functions across the elements.
Having used boost::adaptors for various useful tasks such as filtering or indirecting containers without reconstructing them first, I figure I basically want to be able to do something like this:
auto myRange = boost::adaptors::nested(myVector, functor);
Where functor is some lambda that yanks nested ranges out of each row in my matrix, something like this:
auto functor = [](auto& it) { return boost::iterator_range(it.begin(), it.end(); }
Of course, boost::adaptors::nested doesn't exist. So how can I flatten this 2D array without copying Obj and without creating another flattened container first? The answer should be reasonably efficient while minimising the amount of code and boilerplate.
The answer is indeed to write an adaptor. It will need to keep track of the iterator in the outer container, and an iterator within the inner container.
Here is an example implementation, that only supports forward_iterator semantics, and const access — I'll leave a more complete implementation to you!
#include <cstddef>
#include <iterator>
template <typename V>
struct flat_view {
V &v;
typedef typename V::value_type inner_type;
typedef typename inner_type::value_type value_type;
typedef typename inner_type::reference reference;
typedef typename inner_type::const_reference const_reference;
struct const_iterator {
typedef std::forward_iterator_tag iterator_category;
typedef typename std::iterator_traits<typename inner_type::const_iterator>::value_type value_type;
typedef typename std::iterator_traits<typename inner_type::const_iterator>::pointer pointer;
typedef typename std::iterator_traits<typename inner_type::const_iterator>::reference reference;
typedef ptrdiff_t difference_type;
typename inner_type::const_iterator i,i_end;
typename V::const_iterator o,o_end;
bool at_end;
const_iterator(): at_end(true) {}
const_iterator(typename V::const_iterator vb,typename V::const_iterator ve):
o(vb), o_end(ve), at_end(vb==ve)
{
if (!at_end) {
i=vb->begin();
i_end=vb->end();
}
}
const_iterator &operator++() {
if (at_end) return *this;
if (i!=i_end) ++i;
while (!at_end && i==i_end) {
if (++o==o_end)
at_end=true;
else {
i=o->begin();
i_end=o->end();
}
}
return *this;
}
const_iterator &operator++(int) {
iterator c(*this);
++*this;
return c;
}
bool operator==(const const_iterator &x) const {
return (at_end && x.at_end) || (o==x.o && i==x.i);
}
bool operator!=(const const_iterator &x) const { return !(*this==x); }
reference operator*() const { return *i; }
pointer operator->() const { return &*i; }
};
typedef const_iterator iterator;
explicit flat_view(V &v_): v(v_) {};
iterator begin() const { return iterator(v.begin(),v.end()); }
iterator end() const { return iterator(); }
const_iterator cbegin() const { return const_iterator(v.begin(),v.end()); }
const_iterator cend() const { return const_iterator(); }
};
template <typename V>
flat_view<V> make_flat_view(V &v) { return flat_view<V>(v); }
Quick demo:
#include <iostream>
#include <algorithm>
#include <vector>
int main() {
std::vector<std::vector<double>> v={
{1,2,3,4},
{},
{10,9,8,7},
{5,6}
};
auto f=make_flat_view(v);
std::copy(f.begin(),f.end(),std::ostream_iterator<double>(std::cout," "));
std::cout << "\n";
}
produces:
1 2 3 4 10 9 8 7 5 6
Very new to iterators, and having quite a bit of trouble here.
The error seems very simple, but i'm not sure how to define a type iterator within a class template.
Help would be very appreciated!
Header File:
template<class T>
class e
{
private:
set<T> items; //set container for items of type T
public:
typename set<T>::iterator it;
bool add(T);
int size();
typename set<T>::iterator begin(); //return iterator it (beginning of items)
typename set<T>::iterator end(); //return iterator it (end of items)
};
Code block where error occurs:
for(e<CD>::iterator p=updatableAlbumSet.begin(); p!=updatableAlbumSet.end();p++){
((CD)(*p)).saveAlbum(fout);
}
error:
error: no type named 'iterator' in 'e<CD>'
for(e<CD>::iterator p=updatableAlbumSet.begin(); p!=updatableAlbu...
You need to define type of iterator
#include <iostream>
#include <set>
using namespace std;
template<class T>
class e
{
private:
set<T> items; //set container for items of type T
public:
typedef typename set<T>::iterator iterator;
bool add(T item)
{
items.insert(item);
return true;
}
int size();
typename set<T>::iterator begin() //return iterator it (beginning of items)
{
return items.begin();
}
typename set<T>::iterator end() //return iterator it (end of items)
{
return items.end();
}
};
int main()
{
e<int> updatableAlbumSet;
updatableAlbumSet.add(1);
updatableAlbumSet.add(2);
updatableAlbumSet.add(3);
for(e<int>::iterator p=updatableAlbumSet.begin(); p!=updatableAlbumSet.end();p++)
{
//do something
cout<<*p<<endl;
}
return 0;
}
Modified code using some custom class in set:
#include <iostream>
#include <set>
using namespace std;
template<class T, class Comp>
class e
{
private:
set<T, Comp> items; //set container for items of type T
public:
e(Comp cmp):items(cmp)
{
}
typedef typename set<T, Comp>::iterator iterator;
bool add(T item)
{
items.insert(item);
return true;
}
int size();
typename set<T, Comp>::iterator begin() //return iterator it (beginning of items)
{
return items.begin();
}
typename set<T, Comp>::iterator end() //return iterator it (end of items)
{
return items.end();
}
};
struct CD{
CD(int y):x(y){}
int x;
};
bool compare(CD obj1, CD obj2)
{
return obj1.x < obj2.x;
}
int main()
{
typedef bool(*FnPtr)(CD, CD);
FnPtr fnPtr = compare;
e<CD, FnPtr> updatableAlbumSet(fnPtr);
CD obj1(1);
CD obj2(2);
CD obj3(3);
updatableAlbumSet.add(obj1);
updatableAlbumSet.add(obj2);
updatableAlbumSet.add(obj3);
for(e<CD, FnPtr >::iterator p = updatableAlbumSet.begin();
p!=updatableAlbumSet.end();
p++)
{
//do something
cout<<(*p).x<<endl;
}
return 0;
}
Is there a malloc/free based allocator in the STL? If not, does anyone know of a simple copy/paste one? I need it for a map that must not call new/delete.
First, I'd note that changing the allocator for the map itself won't change the allocation used by the objects stored in the map. For example, if you do something like:
std::map<std::string, int, my_allocator<std::pair<const std::string, int> > m;
The map itself will allocate memory using the specified allocator, but when the std::strings in the map allocate memory, they'll still use the default allocator (which will use new and delete. So, if you need to avoid new and delete in general, you have to ensure that not only the map itself uses the right allocator, but that any objects it stores do the same (I know that's probably stating the obvious, but I've overlooked it, so maybe it's worth mentioning).
With that proviso, on with the code:
#ifndef ALLOCATOR_H_INC_
#define ALLOCATOR_H_INC_
#include <stdlib.h>
#include <new>
#include <limits>
namespace JVC {
template <class T>
struct allocator {
typedef size_t size_type;
typedef ptrdiff_t difference_type;
typedef T* pointer;
typedef const T* const_pointer;
typedef T& reference;
typedef const T& const_reference;
typedef T value_type;
template <class U> struct rebind { typedef allocator<U> other; };
allocator() throw() {}
allocator(const allocator&) throw() {}
template <class U> allocator(const allocator<U>&) throw(){}
~allocator() throw() {}
pointer address(reference x) const { return &x; }
const_pointer address(const_reference x) const { return &x; }
pointer allocate(size_type s, void const * = 0) {
if (0 == s)
return NULL;
pointer temp = (pointer)malloc(s * sizeof(T));
if (temp == NULL)
throw std::bad_alloc();
return temp;
}
void deallocate(pointer p, size_type) {
free(p);
}
size_type max_size() const throw() {
return std::numeric_limits<size_t>::max() / sizeof(T);
}
void construct(pointer p, const T& val) {
new((void *)p) T(val);
}
void destroy(pointer p) {
p->~T();
}
};
}
#endif
And, a little test code:
#include <map>
#include <vector>
#include <iostream>
#include <string>
#include <iterator>
#include "allocator.h"
// Technically this isn't allowed, but it's only demo code, so we'll live with it.
namespace std {
std::ostream &operator<<(std::ostream &os, std::pair<std::string, int> const &c) {
return os << c.first << ": " << c.second;
}
}
int main() {
std::map<std::string, int, std::less<std::string>,
JVC::allocator<std::pair<const std::string, int> > > stuff;
stuff["string 1"] = 1;
stuff["string 2"] = 2;
stuff["string 3"] = 3;
std::copy(stuff.begin(), stuff.end(),
std::ostream_iterator<std::pair<std::string, int> >(std::cout, "\n"));
return 0;
}
Indeed, as #MichaelBurr suggests, Stephen J, Lavavej's 'mallocator' is what you're looking for. I just got updated and prettied-up code for it in this answer by #Arnaud today, do have a look.
I'm looking for a C++ container-like class that wraps a typed array of objects that are not necessarily initialized and don't have to be default-constructible or copy-constructible. This would be interesting for RAII objects that have no well-defined copy semantics. Such a container-like class seems to be fairly easy to write (using an allocator to allocate uninitialized memory and placement new). Is there something like this in Boost that I have just overlooked? I'm not looking for std::vector (which requires its elements to be copy-constructible) or a pointer container, but for something like this:
#include <cstddef>
#include <memory>
#include <vector>
#include <algorithm>
#include <iostream>
template< typename T, typename Alloc = std::allocator<T> >
class FixedVector {
public:
typedef typename Alloc::value_type value_type;
typedef typename Alloc::pointer pointer;
typedef typename Alloc::reference reference;
typedef typename Alloc::const_pointer const_pointer;
typedef typename Alloc::const_reference const_reference;
typedef typename Alloc::size_type size_type;
typedef typename Alloc::difference_type difference_type;
typedef pointer iterator;
typedef const_pointer const_iterator;
explicit FixedVector(size_type size, const Alloc& allocator = Alloc()):
m_alloc(allocator),
m_size(size),
m_data(m_alloc.allocate(size)),
m_constructed(size) { }
FixedVector(const FixedVector& other):
m_alloc(other.m_alloc),
m_size(other.m_size),
m_data(m_alloc.allocate(m_size)),
m_constructed(other.m_constructed) {
for (size_type i = 0; i != m_size; ++i) {
if (m_constructed[i]) m_alloc.construct(m_alloc.address(m_data[i]), other[i]);
}
}
~FixedVector() {
for (size_type i = 0; i != m_size; ++i) {
if (m_constructed[i]) m_alloc.destroy(m_alloc.address(m_data[i]));
}
m_alloc.deallocate(m_data, m_size);
}
FixedVector& operator=(FixedVector other) {
other.swap(*this);
return *this;
}
// operator[] and other unimportant stuff
void swap(FixedVector& other) {
std::swap(m_alloc, other.m_alloc);
std::swap(m_size, other.m_size);
std::swap(m_data, other.m_data);
std::swap(m_constructed, other.m_constructed);
}
void construct(size_type index) {
new (m_alloc.address(m_data[index])) T();
m_constructed[index] = true;
}
template<typename U>
void construct(size_type index, U& val) {
new (m_alloc.address(m_data[index])) T(val);
m_constructed[index] = true;
}
template<typename U>
void construct(size_type index, const U& val) {
new (m_alloc.address(m_data[index])) T(val);
m_constructed[index] = true;
}
private:
Alloc m_alloc;
size_type m_size;
pointer m_data;
std::vector<bool> m_constructed;
};
template<typename T, typename Alloc>
void swap(FixedVector<T, Alloc>& first, FixedVector<T, Alloc>& second) {
first.swap(second);
}
namespace std {
template<typename T, typename Alloc>
void swap(FixedVector<T, Alloc>& first, FixedVector<T, Alloc>& second) {
first.swap(second);
}
}
class Test {
public:
explicit Test(int val): m_val(val) {
std::cout << "Test::Test(" << val << ')' << std::endl;
}
~Test() {
std::cout << "Test::~Test() [with m_val = " << m_val << ']' << std::endl;
}
int val() const {
return m_val;
}
private:
int m_val;
Test(const Test&);
Test& operator=(const Test&);
};
template<typename Char, typename Traits>
std::basic_ostream<Char, Traits>& operator<<(std::basic_ostream<Char, Traits>& stream, const Test& object) {
return stream << object.val();
}
int main() {
typedef FixedVector<Test> FVT;
FVT w(10);
w.construct(7, 7);
w.construct(2, 2);
std::cout << "w[2] = " << w[2] << std::endl;
}
The solution should work in C++03 (e.g. no move semantics allowed). The question is a bit academical—I'm just wondering why such a class doesn't seem to exist in Boost.
Such a container-like class seems to
be fairly easy to write (using an
allocator to allocate uninitialized
memory and placement new).
And that is exactly what std::vector does. To use placement new, you would have to make a copy.
void store(const T& value)
{
new (storage) T(value); //<-- invokes copy constructor
}
Perhaps boost::ptr_vector would work for non-copyable types (you'd give it pointers).
#include <boost/noncopyable.hpp>
#include <boost/ptr_container/ptr_vector.hpp>
#include <iostream>
struct X: boost::noncopyable
{
X(int x): x(x) {}
int x;
};
int main()
{
boost::ptr_vector<X> vec;
for (int i = 1; i < 10; ++i) {
vec.push_back(new X(i));
}
for (size_t i = 0; i != vec.size(); ++i) {
std::cout << vec[i].x << '\n';
}
}
And in C++0x, containers will accept non-copyable types as long as they are movable (which should normally be implementable for non-copyable types).
In C++0x, the elements of a std::vector don't have to be copy-constructible as long as they're movable.