add feature detection machinery

This commit is contained in:
Ferdinand Bachmann
2020-04-18 12:39:31 +02:00
parent ce9d000673
commit 5feb3f4f60
7 changed files with 315 additions and 222 deletions

View File

@ -0,0 +1,22 @@
#ifndef _RING_BUFFER_CONFIG_H
#define _RING_BUFFER_CONFIG_H
#ifdef RING_BUFFER_NOEXCEPT
#define NOEXCEPT(x) noexcept(x)
#else
#define NOEXCEPT(x)
#endif
#ifdef RING_BUFFER_CONSTEXPR
#define CONSTEXPR constexpr
#else
#define CONSTEXPR
#endif
#ifdef RING_BUFFER_CONSTEXPR_DESTRUCTORS
#define CONSTEXPR_D CONSTEXPR
#else
#define CONSTEXPR_D
#endif
#endif

View File

@ -0,0 +1,221 @@
#ifndef _RING_BUFFER_ITERATOR_H
#define _RING_BUFFER_ITERATOR_H
#include <iterator>
#include <ring-buffer-config.h>
template <typename Container>
class ring_buffer_iterator {
private:
using size_type = typename Container::size_type;
using value_type = typename std::iterator_traits<ring_buffer_iterator>::value_type;
using difference_type = typename std::iterator_traits<ring_buffer_iterator>::difference_type;
using reference = typename std::iterator_traits<ring_buffer_iterator>::reference;
using pointer = typename std::iterator_traits<ring_buffer_iterator>::pointer;
Container* container;
size_type front;
size_type index;
public:
ring_buffer_iterator() = default;
~ring_buffer_iterator() = default;
ring_buffer_iterator(Container& container, size_type front = 0, size_type index = 0) : container(&container), front(front), index(index) {}
ring_buffer_iterator(const ring_buffer_iterator&) = default;
ring_buffer_iterator(ring_buffer_iterator&&) = default;
ring_buffer_iterator& operator=(const ring_buffer_iterator&) = default;
ring_buffer_iterator& operator=(ring_buffer_iterator&&) = default;
ring_buffer_iterator& operator+=(difference_type n) {
index += n;
}
ring_buffer_iterator& operator-=(difference_type n) {
index -= n;
}
ring_buffer_iterator operator+(difference_type n) const {
return {container, front, index + n};
}
ring_buffer_iterator operator-(difference_type n) const {
return {container, front, index - n};
}
reference operator*() {
return *(container->begin() + (front + index) % container->size());
}
pointer operator->() {
return &**this;
}
reference operator[](difference_type n) {
return *(*this + n);
}
ring_buffer_iterator& operator++() {
index++;
return *this;
}
ring_buffer_iterator operator++(int) {
ring_buffer_iterator old = *this;
*this++;
return old;
}
ring_buffer_iterator& operator--() {
index--;
return *this;
}
ring_buffer_iterator operator--(int) {
ring_buffer_iterator old = *this;
*this--;
return old;
}
bool operator==(const ring_buffer_iterator& other) const {
return index == other.index;
}
bool operator!=(const ring_buffer_iterator& other) const {
return index != other.index;
}
bool operator<(const ring_buffer_iterator& other) const {
return index < other.index;
}
bool operator>(const ring_buffer_iterator& other) const {
return index > other.index;
}
bool operator<=(const ring_buffer_iterator& other) const {
return index <= other.index;
}
bool operator>=(const ring_buffer_iterator& other) const {
return index >= other.index;
}
friend ring_buffer_iterator operator+( difference_type n, const ring_buffer_iterator& it) {
return it + n;
}
friend void swap(ring_buffer_iterator& a, ring_buffer_iterator& b) {
using std::swap;
swap(a.container, b.container);
swap(a.front, b.front);
swap(a.index, b.index);
}
};
template <typename Container>
class ring_buffer_const_iterator {
private:
using size_type = typename Container::size_type;
using value_type = typename std::iterator_traits<ring_buffer_const_iterator>::value_type;
using difference_type = typename std::iterator_traits<ring_buffer_const_iterator>::difference_type;
using reference = typename std::iterator_traits<ring_buffer_const_iterator>::reference;
using pointer = typename std::iterator_traits<ring_buffer_const_iterator>::pointer;
const Container* container;
size_type front{};
size_type index{};
public:
ring_buffer_const_iterator() = default;
~ring_buffer_const_iterator() = default;
ring_buffer_const_iterator(const Container& container, size_type front = 0, size_type index = 0) : container(&container), front(front), index(index) {}
ring_buffer_const_iterator(const ring_buffer_const_iterator&) = default;
ring_buffer_const_iterator(ring_buffer_const_iterator&&) = default;
ring_buffer_const_iterator& operator=(const ring_buffer_const_iterator&) = default;
ring_buffer_const_iterator& operator=(ring_buffer_const_iterator&&) = default;
ring_buffer_const_iterator& operator+=(difference_type n) {
index += n;
}
ring_buffer_const_iterator& operator-=(difference_type n) {
index -= n;
}
ring_buffer_const_iterator operator+(difference_type n) const {
return {container, front, index + n};
}
ring_buffer_const_iterator operator-(difference_type n) const {
return {container, front, index - n};
}
reference operator*() const {
return *(container->begin() + (front + index) % container->size());
}
pointer operator->() const {
return &**this;
}
reference operator[](difference_type n) const {
return *(*this + n);
}
ring_buffer_const_iterator& operator++() {
index++;
return *this;
}
ring_buffer_const_iterator operator++(int) {
ring_buffer_const_iterator old = *this;
*this++;
return old;
}
ring_buffer_const_iterator& operator--() {
index--;
return *this;
}
ring_buffer_const_iterator operator--(int) {
ring_buffer_const_iterator old = *this;
*this--;
return old;
}
bool operator==(const ring_buffer_const_iterator& other) const {
return index == other.index;
}
bool operator!=(const ring_buffer_const_iterator& other) const {
return index != other.index;
}
bool operator<(const ring_buffer_const_iterator& other) const {
return index < other.index;
}
bool operator>(const ring_buffer_const_iterator& other) const {
return index > other.index;
}
bool operator<=(const ring_buffer_const_iterator& other) const {
return index <= other.index;
}
bool operator>=(const ring_buffer_const_iterator& other) const {
return index >= other.index;
}
friend ring_buffer_const_iterator operator+( difference_type n, const ring_buffer_const_iterator& it) {
return it + n;
}
friend void swap(ring_buffer_const_iterator& a, ring_buffer_const_iterator& b) {
using std::swap;
swap(a.container, b.container);
swap(a.front, b.front);
swap(a.index, b.index);
}
};
namespace std {
template <typename Container>
class iterator_traits<ring_buffer_iterator<Container>> {
public:
using difference_type = typename std::make_signed<typename Container::size_type>::type;
using value_type = typename Container::value_type;
using pointer = value_type*;
using reference = value_type&;
using iterator_category = std::random_access_iterator_tag;
};
template <typename Container>
class iterator_traits<ring_buffer_const_iterator<Container>> {
public:
using difference_type = typename std::make_signed<typename Container::size_type>::type;
using value_type = const typename Container::value_type;
using pointer = const value_type*;
using reference = const value_type&;
using iterator_category = std::random_access_iterator_tag;
};
}
#endif

View File

@ -1,198 +1,8 @@
#include <type_traits>
#include <utility>
#include <iterator>
#ifndef _RING_BUFFER_H
#define _RING_BUFFER_H
template <typename Container>
class ring_buffer_iterator {
private:
using size_type = typename Container::size_type;
using value_type = typename std::iterator_traits<ring_buffer_iterator>::value_type;
using difference_type = typename std::iterator_traits<ring_buffer_iterator>::difference_type;
using reference = typename std::iterator_traits<ring_buffer_iterator>::reference;
using pointer = typename std::iterator_traits<ring_buffer_iterator>::pointer;
Container* container;
size_type front;
size_type index;
public:
ring_buffer_iterator() = default;
~ring_buffer_iterator() = default;
ring_buffer_iterator(Container& container, size_type front = 0, size_type index = 0) : container(&container), front(front), index(index) {}
ring_buffer_iterator(const ring_buffer_iterator&) = default;
ring_buffer_iterator(ring_buffer_iterator&&) = default;
ring_buffer_iterator& operator=(const ring_buffer_iterator&) = default;
ring_buffer_iterator& operator=(ring_buffer_iterator&&) = default;
ring_buffer_iterator& operator+=(difference_type n) {
index += n;
}
ring_buffer_iterator& operator-=(difference_type n) {
index -= n;
}
ring_buffer_iterator operator+(difference_type n) const {
return {container, front, index + n};
}
ring_buffer_iterator operator-(difference_type n) const {
return {container, front, index - n};
}
reference operator*() {
return *(container->begin() + (front + index) % container->size());
}
pointer operator->() {
return &**this;
}
reference operator[](difference_type n) {
return *(*this + n);
}
ring_buffer_iterator& operator++() {
index++;
return *this;
}
ring_buffer_iterator operator++(int) {
ring_buffer_iterator old = *this;
*this++;
return old;
}
ring_buffer_iterator& operator--() {
index--;
return *this;
}
ring_buffer_iterator operator--(int) {
ring_buffer_iterator old = *this;
*this--;
return old;
}
bool operator==(const ring_buffer_iterator& other) const {
return index == other.index;
}
bool operator!=(const ring_buffer_iterator& other) const {
return index != other.index;
}
bool operator<(const ring_buffer_iterator& other) const {
return index < other.index;
}
bool operator>(const ring_buffer_iterator& other) const {
return index > other.index;
}
bool operator<=(const ring_buffer_iterator& other) const {
return index <= other.index;
}
bool operator>=(const ring_buffer_iterator& other) const {
return index >= other.index;
}
friend ring_buffer_iterator operator+( difference_type n, const ring_buffer_iterator& it) {
return it + n;
}
friend void swap(ring_buffer_iterator& a, ring_buffer_iterator& b) {
using std::swap;
swap(a.container, b.container);
swap(a.front, b.front);
swap(a.index, b.index);
}
};
template <typename Container>
class ring_buffer_const_iterator {
private:
using size_type = typename Container::size_type;
using value_type = typename std::iterator_traits<ring_buffer_const_iterator>::value_type;
using difference_type = typename std::iterator_traits<ring_buffer_const_iterator>::difference_type;
using reference = typename std::iterator_traits<ring_buffer_const_iterator>::reference;
using pointer = typename std::iterator_traits<ring_buffer_const_iterator>::pointer;
const Container* container;
size_type front{};
size_type index{};
public:
ring_buffer_const_iterator() = default;
~ring_buffer_const_iterator() = default;
ring_buffer_const_iterator(const Container& container, size_type front = 0, size_type index = 0) : container(&container), front(front), index(index) {}
ring_buffer_const_iterator(const ring_buffer_const_iterator&) = default;
ring_buffer_const_iterator(ring_buffer_const_iterator&&) = default;
ring_buffer_const_iterator& operator=(const ring_buffer_const_iterator&) = default;
ring_buffer_const_iterator& operator=(ring_buffer_const_iterator&&) = default;
ring_buffer_const_iterator& operator+=(difference_type n) {
index += n;
}
ring_buffer_const_iterator& operator-=(difference_type n) {
index -= n;
}
ring_buffer_const_iterator operator+(difference_type n) const {
return {container, front, index + n};
}
ring_buffer_const_iterator operator-(difference_type n) const {
return {container, front, index - n};
}
reference operator*() const {
return *(container->begin() + (front + index) % container->size());
}
pointer operator->() const {
return &**this;
}
reference operator[](difference_type n) const {
return *(*this + n);
}
ring_buffer_const_iterator& operator++() {
index++;
return *this;
}
ring_buffer_const_iterator operator++(int) {
ring_buffer_const_iterator old = *this;
*this++;
return old;
}
ring_buffer_const_iterator& operator--() {
index--;
return *this;
}
ring_buffer_const_iterator operator--(int) {
ring_buffer_const_iterator old = *this;
*this--;
return old;
}
bool operator==(const ring_buffer_const_iterator& other) const {
return index == other.index;
}
bool operator!=(const ring_buffer_const_iterator& other) const {
return index != other.index;
}
bool operator<(const ring_buffer_const_iterator& other) const {
return index < other.index;
}
bool operator>(const ring_buffer_const_iterator& other) const {
return index > other.index;
}
bool operator<=(const ring_buffer_const_iterator& other) const {
return index <= other.index;
}
bool operator>=(const ring_buffer_const_iterator& other) const {
return index >= other.index;
}
friend ring_buffer_const_iterator operator+( difference_type n, const ring_buffer_const_iterator& it) {
return it + n;
}
friend void swap(ring_buffer_const_iterator& a, ring_buffer_const_iterator& b) {
using std::swap;
swap(a.container, b.container);
swap(a.front, b.front);
swap(a.index, b.index);
}
};
#include <ring-buffer-config.h>
#include <ring-buffer-iterator.h>
template <typename Container>
class basic_ring_buffer {
@ -207,8 +17,8 @@ private:
size_type front_index{};
public:
basic_ring_buffer() noexcept = default;
~basic_ring_buffer() noexcept = default;
CONSTEXPR basic_ring_buffer() NOEXCEPT() = default;
CONSTEXPR_D ~basic_ring_buffer() NOEXCEPT() = default;
basic_ring_buffer(const basic_ring_buffer& other) = default;
basic_ring_buffer(basic_ring_buffer&& other) = default;
basic_ring_buffer& operator=(const basic_ring_buffer& other) = default;
@ -241,28 +51,8 @@ public:
}
};
namespace std {
template <typename Container>
class iterator_traits<ring_buffer_iterator<Container>> {
public:
using difference_type = typename std::make_signed<typename Container::size_type>::type;
using value_type = typename Container::value_type;
using pointer = value_type*;
using reference = value_type&;
using iterator_category = std::random_access_iterator_tag;
};
template <typename Container>
class iterator_traits<ring_buffer_const_iterator<Container>> {
public:
using difference_type = typename std::make_signed<typename Container::size_type>::type;
using value_type = const typename Container::value_type;
using pointer = const value_type*;
using reference = const value_type&;
using iterator_category = std::random_access_iterator_tag;
};
}
#include <array>
template <typename T, size_t N>
using ring_buffer = basic_ring_buffer<std::array<T, N>>;
#endif