OpenFPGA/libs/libvtrutil/src/vtr_vector.h

145 lines
4.9 KiB
C++

#ifndef VTR_VECTOR
#define VTR_VECTOR
#include <vector>
#include <cstddef>
#include <iterator>
#include "vtr_range.h"
namespace vtr {
//A std::vector container which is indexed by K (instead of size_t).
//
//The main use of this container is to behave like a std::vector which is
//indexed by a vtr::StrongId. It assumes that K is explicitly convertable to size_t
//(i.e. via operator size_t()), and can be explicitly constructed from a size_t.
//
//If you need more std::map-like (instead of std::vector-like) behaviour see
//vtr::vector_map.
template<typename K, typename V>
class vector : private std::vector<V> {
public:
typedef K key_type;
class key_iterator;
typedef vtr::Range<key_iterator> key_range;
public:
//Pass through std::vector's types
using typename std::vector<V>::value_type;
using typename std::vector<V>::allocator_type;
using typename std::vector<V>::reference;
using typename std::vector<V>::const_reference;
using typename std::vector<V>::pointer;
using typename std::vector<V>::const_pointer;
using typename std::vector<V>::iterator;
using typename std::vector<V>::const_iterator;
using typename std::vector<V>::reverse_iterator;
using typename std::vector<V>::const_reverse_iterator;
using typename std::vector<V>::difference_type;
using typename std::vector<V>::size_type;
//Pass through std::vector's methods
using std::vector<V>::vector;
using std::vector<V>::begin;
using std::vector<V>::end;
using std::vector<V>::rbegin;
using std::vector<V>::rend;
using std::vector<V>::cbegin;
using std::vector<V>::cend;
using std::vector<V>::crbegin;
using std::vector<V>::crend;
using std::vector<V>::size;
using std::vector<V>::max_size;
using std::vector<V>::resize;
using std::vector<V>::capacity;
using std::vector<V>::empty;
using std::vector<V>::reserve;
using std::vector<V>::shrink_to_fit;
using std::vector<V>::front;
using std::vector<V>::back;
using std::vector<V>::data;
using std::vector<V>::assign;
using std::vector<V>::push_back;
using std::vector<V>::pop_back;
using std::vector<V>::insert;
using std::vector<V>::erase;
using std::vector<V>::swap;
using std::vector<V>::clear;
using std::vector<V>::emplace;
using std::vector<V>::emplace_back;
using std::vector<V>::get_allocator;
//Don't include operator[] and at() from std::vector,
//since we redine them to take key_type instead of size_t
reference operator[](const key_type id) {
auto i = size_t(id);
return std::vector<V>::operator[](i);
}
const_reference operator[](const key_type id) const {
auto i = size_t(id);
return std::vector<V>::operator[](i);
}
reference at(const key_type id) {
auto i = size_t(id);
return std::vector<V>::at(i);
}
const_reference at(const key_type id) const {
auto i = size_t(id);
return std::vector<V>::at(i);
}
//Returns a range containing the keys
key_range keys() const {
return vtr::make_range(key_begin(), key_end());
}
public:
//Iterator class which is convertable to the key_type
//This allows end-users to call the parent class's keys() member
//to iterate through the keys with a range-based for loop
class key_iterator : public std::iterator<std::bidirectional_iterator_tag, key_type> {
public:
//We use the intermediate type my_iter to avoid a potential ambiguity for which
//clang generates errors and warnings
using my_iter = typename std::iterator<std::bidirectional_iterator_tag, K>;
using typename my_iter::iterator;
using typename my_iter::pointer;
using typename my_iter::reference;
using typename my_iter::value_type;
key_iterator(key_iterator::value_type init)
: value_(init) {}
//vtr::vector assumes that the key time is convertable to size_t and
//that all the underlying IDs are zero-based and contiguous. That means
//we can just increment the underlying Id to build the next key.
key_iterator operator++() {
value_ = value_type(size_t(value_) + 1);
return *this;
}
key_iterator operator--() {
value_ = value_type(size_t(value_) - 1);
return *this;
}
reference operator*() { return value_; }
pointer operator->() { return &value_; }
friend bool operator==(const key_iterator lhs, const key_iterator rhs) { return lhs.value_ == rhs.value_; }
friend bool operator!=(const key_iterator lhs, const key_iterator rhs) { return !(lhs == rhs); }
private:
value_type value_;
};
private:
key_iterator key_begin() const { return key_iterator(key_type(0)); }
key_iterator key_end() const { return key_iterator(key_type(size())); }
};
} // namespace vtr
#endif