12 Commits

Author SHA1 Message Date
3dc81a4e8e bump version to 1.0.1 2025-05-12 15:37:45 +02:00
349a24bfdb test/constexpr-array-shim: add required import of <cstddef> for size_t 2025-05-12 15:35:58 +02:00
010362d1f6 test: add additional tests around swapping and iterators 2025-05-12 15:30:46 +02:00
ab1a477757 ring-buffer-iterator: remove unnecessary conditional noexcept
container_ptr is a built-in pointer type, and will always be noexcept to
swap.
2025-05-12 15:30:25 +02:00
4a019ad63c fixes ring-buffer-iterator swap() 2025-05-12 15:29:28 +02:00
746672a6c1 ring-buffer: add support for swapping ring buffers 2025-05-12 15:28:07 +02:00
1a8b098ed0 ring-buffer-iterator: fix postfix increment/decrement
this silently did the wrong thing on g++ (precedence of postfix ++/--)
and didn't compile on clang++. The correct solution is to
prefix-increment, which has no precedence issues and calls the correct
function. Postfix-increment with correct precedence would have resulted
in a stack overflow anyway.
2025-05-12 15:20:33 +02:00
3bad408674 CMake: detect/features.cmake: fix try_compile if CXX_STANDARD or CXX_EXTENSIONS unset 2025-05-12 14:17:15 +02:00
d9314150c2 constexpr_array: fix compile error in constexpr_array shim 2021-03-10 13:55:23 +01:00
5a6309dc28 ring_buffer_iterator: add it1 - it2 operator 2021-03-10 13:46:27 +01:00
795a4c3be7 ring_buffer_iterator: whitespace changes 2021-03-10 13:46:07 +01:00
5a021c46d0 add MIT license 2021-02-09 21:44:50 +01:00
9 changed files with 157 additions and 23 deletions

21
LICENSE Normal file
View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) [year] [fullname]
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@ -1,8 +1,5 @@
try_compile(cxx-least-11 ${CMAKE_BINARY_DIR}/detect ${CMAKE_SOURCE_DIR}/detect/cxxstd.cpp
COMPILE_DEFINITIONS -DCXX_STANDARD=201103
CXX_STANDARD ${CMAKE_CXX_STANDARD}
CXX_STANDARD_REQUIRED ${CMAKE_CXX_STANDARD_REQUIRED}
CXX_EXTENSIONS ${CMAKE_CXX_EXTENSIONS}
)
if(NOT cxx-least-11)
@ -16,20 +13,13 @@ endif()
try_compile(cxx-least-14 ${CMAKE_BINARY_DIR}/detect ${CMAKE_SOURCE_DIR}/detect/cxxstd.cpp
COMPILE_DEFINITIONS -DCXX_STANDARD=201402
CXX_STANDARD ${CMAKE_CXX_STANDARD}
CXX_STANDARD_REQUIRED ${CMAKE_CXX_STANDARD_REQUIRED}
CXX_EXTENSIONS ${CMAKE_CXX_EXTENSIONS}
)
if(cxx-least-14)
set(RING_BUFFER_CONSTEXPR ON)
message(STATUS "Enabling RING_BUFFER_CONSTEXPR (C++14 and up)")
endif()
try_compile(constexpr-destructors-compile ${CMAKE_BINARY_DIR}/detect ${CMAKE_SOURCE_DIR}/detect/constexpr_destructors.cpp
CXX_STANDARD ${CMAKE_CXX_STANDARD}
CXX_STANDARD_REQUIRED ${CMAKE_CXX_STANDARD_REQUIRED}
CXX_EXTENSIONS ${CMAKE_CXX_EXTENSIONS}
)
try_compile(constexpr-destructors-compile ${CMAKE_BINARY_DIR}/detect ${CMAKE_SOURCE_DIR}/detect/constexpr_destructors.cpp)
if(constexpr-destructors-compile)
set(RING_BUFFER_CONSTEXPR_DESTRUCTORS ON)
message(STATUS "Enabling RING_BUFFER_CONSTEXPR_DESTRUCTORS (C++20 and up)")

View File

@ -41,6 +41,10 @@ public:
return {*container_ptr, front, index - n};
}
CONSTEXPR difference_type operator-(const ring_buffer_iterator& other) const NOEXCEPT {
return index - other.index;
}
CONSTEXPR reference operator*() COND_NOEXCEPT(noexcept(container_ptr->begin()) && noexcept(container_ptr->size())) {
return *(container_ptr->begin() + (front + index) % container_ptr->size());
}
@ -57,7 +61,7 @@ public:
}
CONSTEXPR ring_buffer_iterator operator++(int) NOEXCEPT {
ring_buffer_iterator old = *this;
*this++;
++*this;
return old;
}
CONSTEXPR ring_buffer_iterator& operator--() NOEXCEPT {
@ -66,7 +70,7 @@ public:
}
CONSTEXPR ring_buffer_iterator operator--(int) NOEXCEPT {
ring_buffer_iterator old = *this;
*this--;
--*this;
return old;
}
@ -90,12 +94,12 @@ public:
return index >= other.index;
}
CONSTEXPR friend ring_buffer_iterator operator+( difference_type n, const ring_buffer_iterator& it) NOEXCEPT {
CONSTEXPR friend ring_buffer_iterator operator+(difference_type n, const ring_buffer_iterator& it) NOEXCEPT {
return it + n;
}
CONSTEXPR friend void swap(ring_buffer_iterator& a, ring_buffer_iterator& b) COND_NOEXCEPT(noexcept(std::swap(a.container, b.container))) {
CONSTEXPR friend void swap(ring_buffer_iterator& a, ring_buffer_iterator& b) NOEXCEPT {
using std::swap;
swap(a.container, b.container);
swap(a.container_ptr, b.container_ptr);
swap(a.front, b.front);
swap(a.index, b.index);
}
@ -137,6 +141,10 @@ public:
return {*container_ptr, front, index - n};
}
CONSTEXPR difference_type operator-(const ring_buffer_const_iterator& other) const NOEXCEPT {
return index - other.index;
}
CONSTEXPR reference operator*() const COND_NOEXCEPT(noexcept(container_ptr->cbegin()) && noexcept(container_ptr->size())) {
return *(container_ptr->cbegin() + (front + index) % container_ptr->size());
}
@ -153,7 +161,7 @@ public:
}
CONSTEXPR ring_buffer_const_iterator operator++(int) NOEXCEPT {
ring_buffer_const_iterator old = *this;
*this++;
++*this;
return old;
}
CONSTEXPR ring_buffer_const_iterator& operator--() NOEXCEPT {
@ -162,7 +170,7 @@ public:
}
CONSTEXPR ring_buffer_const_iterator operator--(int) NOEXCEPT {
ring_buffer_const_iterator old = *this;
*this--;
--*this;
return old;
}
@ -186,12 +194,12 @@ public:
return index >= other.index;
}
CONSTEXPR friend ring_buffer_const_iterator operator+( difference_type n, const ring_buffer_const_iterator& it) NOEXCEPT {
CONSTEXPR friend ring_buffer_const_iterator operator+(difference_type n, const ring_buffer_const_iterator& it) NOEXCEPT {
return it + n;
}
CONSTEXPR friend void swap(ring_buffer_const_iterator& a, ring_buffer_const_iterator& b) COND_NOEXCEPT(noexcept(std::swap(a.container, b.container))) {
CONSTEXPR friend void swap(ring_buffer_const_iterator& a, ring_buffer_const_iterator& b) NOEXCEPT {
using std::swap;
swap(a.container, b.container);
swap(a.container_ptr, b.container_ptr);
swap(a.front, b.front);
swap(a.index, b.index);
}

View File

@ -6,6 +6,14 @@
#include <ring-buffer-config.h>
#include <ring-buffer-iterator.h>
namespace detail {
using std::swap;
template <typename T>
CONSTEXPR void adl_swap(T& a, T&b ) COND_NOEXCEPT(noexcept(swap(a, b))) {
swap(a, b);
}
}
template <typename Container>
class basic_ring_buffer {
public:
@ -71,6 +79,11 @@ public:
CONSTEXPR const_iterator cend() const COND_NOEXCEPT(noexcept(container.size())) {
return {container, front_index, container.size()};
}
CONSTEXPR friend void swap(basic_ring_buffer& a, basic_ring_buffer& b) COND_NOEXCEPT(noexcept(detail::adl_swap(a.container, b.container))) {
using std::swap;
swap(a.container, b.container);
swap(a.front_index, b.front_index);
}
};
template <typename T, size_t N>

View File

@ -1,6 +1,6 @@
{
"name": "cxx-ring-buffer",
"version": "1.0.0",
"version": "1.0.1",
"build": {
"includeDir": "include",
"srcFilter":

View File

@ -1,11 +1,12 @@
#ifndef _CONSTEXPR_ARRAY_SHIM_H
#define _CONSTEXPR_ARRAY_SHIM_H
#include <cstddef>
#include <array>
#if defined( __cpp_lib_array_constexpr) && __cpp_lib_array_constexpr >= 201606L
template <typename T, size_t N>
using constexpr_array = array;
using constexpr_array = std::array<T, N>;
#else
template <typename T, size_t N>
struct constexpr_array {

24
test/iterator-ops.cpp Normal file
View File

@ -0,0 +1,24 @@
#include <vector>
#include <cassert>
#include <ring-buffer.h>
int main() {
ring_buffer<int, 4> buf;
buf.push_back(1);
buf.push_back(2);
buf.push_back(3);
buf.push_back(4);
buf.push_back(5);
buf.push_back(6);
{
auto it = buf.begin();
++it;
it++;
assert(*it == 5);
--it;
it--;
assert(*it == 3);
}
}

View File

@ -0,0 +1,33 @@
#include <vector>
#include <cassert>
#include <ring-buffer.h>
#include <utility>
int main() {
ring_buffer<int, 4> buf1;
buf1.push_back(1);
buf1.push_back(2);
buf1.push_back(3);
buf1.push_back(4);
buf1.push_back(5);
buf1.push_back(6);
ring_buffer<int, 4> buf2;
buf2.push_back(10);
buf2.push_back(20);
buf2.push_back(30);
buf2.push_back(40);
buf2.push_back(50);
buf2.push_back(60);
auto it1 = buf1.begin();
auto it2 = buf2.begin();
std::swap(it1, it2);
{
assert(*it1 == 30);
assert(*it2 == 3);
}
}

44
test/swap-ring-buffer.cpp Normal file
View File

@ -0,0 +1,44 @@
#include <vector>
#include <cassert>
#include <ring-buffer.h>
#include <utility>
int main() {
ring_buffer<int, 4> buf1;
buf1.push_back(1);
buf1.push_back(2);
buf1.push_back(3);
buf1.push_back(4);
buf1.push_back(5);
buf1.push_back(6);
ring_buffer<int, 4> buf2;
buf2.push_back(10);
buf2.push_back(20);
buf2.push_back(30);
buf2.push_back(40);
buf2.push_back(50);
buf2.push_back(60);
std::swap(buf1, buf2);
{
std::vector<int> expected{30, 40, 50, 60};
std::vector<int> actual;
for (int& i : buf1) {
actual.push_back(i);
}
assert(actual == expected);
}
{
std::vector<int> expected{3, 4, 5, 6};
std::vector<int> actual;
for (int& i : buf2) {
actual.push_back(i);
}
assert(actual == expected);
}
}