forked from mpusz/mp-units
feat: simplified inplace_vector
added
This commit is contained in:
@@ -46,6 +46,7 @@ add_mp_units_module(
|
||||
include/mp-units/ext/algorithm.h
|
||||
include/mp-units/ext/contracts.h
|
||||
include/mp-units/ext/fixed_string.h
|
||||
include/mp-units/ext/inplace_vector.h
|
||||
include/mp-units/ext/prime.h
|
||||
include/mp-units/ext/type_name.h
|
||||
include/mp-units/ext/type_traits.h
|
||||
|
137
src/core/include/mp-units/ext/inplace_vector.h
Normal file
137
src/core/include/mp-units/ext/inplace_vector.h
Normal file
@@ -0,0 +1,137 @@
|
||||
// The MIT License (MIT)
|
||||
//
|
||||
// Copyright (c) 2018 Mateusz Pusz
|
||||
//
|
||||
// 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.
|
||||
|
||||
// Very simplified implementation of std::inplace_vector
|
||||
// To be replaced with:
|
||||
// P0843: std::inplace_vector
|
||||
|
||||
#include <mp-units/bits/hacks.h> // IWYU pragma: keep
|
||||
|
||||
#ifndef MP_UNITS_IN_MODULE_INTERFACE
|
||||
#include <mp-units/ext/contracts.h>
|
||||
#include <concepts>
|
||||
#include <cstddef>
|
||||
#include <ranges>
|
||||
#endif
|
||||
|
||||
// NOLINTBEGIN(*-avoid-c-arrays)
|
||||
#pragma once
|
||||
|
||||
namespace mp_units::detail {
|
||||
template<class T, std::size_t N>
|
||||
class inplace_vector {
|
||||
public:
|
||||
using value_type = T;
|
||||
using pointer = T*;
|
||||
using const_pointer = const T*;
|
||||
using reference = value_type&;
|
||||
using const_reference = const value_type&;
|
||||
using size_type = std::size_t;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
using iterator = pointer;
|
||||
using const_iterator = const_pointer;
|
||||
using reverse_iterator = std::reverse_iterator<iterator>;
|
||||
using const_reverse_iterator = std::reverse_iterator<const_iterator>;
|
||||
|
||||
constexpr inplace_vector() noexcept = default;
|
||||
|
||||
// iterators
|
||||
constexpr iterator begin() noexcept { return data(); }
|
||||
constexpr const_iterator begin() const noexcept { return data(); }
|
||||
constexpr iterator end() noexcept { return begin() + size(); }
|
||||
constexpr const_iterator end() const noexcept { return begin() + size(); }
|
||||
constexpr reverse_iterator rbegin() noexcept { return reverse_iterator(end()); }
|
||||
constexpr const_reverse_iterator rbegin() const noexcept { return const_reverse_iterator(end()); }
|
||||
constexpr reverse_iterator rend() noexcept { return reverse_iterator(begin()); }
|
||||
constexpr const_reverse_iterator rend() const noexcept { return const_reverse_iterator(begin()); }
|
||||
|
||||
constexpr const_iterator cbegin() const noexcept { return data(); }
|
||||
constexpr const_iterator cend() const noexcept { return cbegin() + size(); }
|
||||
constexpr const_reverse_iterator crbegin() const noexcept { return const_reverse_iterator(cend()); }
|
||||
constexpr const_reverse_iterator crend() const noexcept { return const_reverse_iterator(cbegin()); }
|
||||
|
||||
[[nodiscard]] constexpr bool empty() const noexcept { return size() == 0; };
|
||||
[[nodiscard]] constexpr size_type size() const noexcept { return size_; }
|
||||
[[nodiscard]] static constexpr size_type max_size() noexcept { return N; }
|
||||
[[nodiscard]] static constexpr size_type capacity() noexcept { return N; }
|
||||
|
||||
// element access
|
||||
constexpr reference operator[](size_type n) { return data_[n]; }
|
||||
constexpr const_reference operator[](size_type n) const { return data_[n]; }
|
||||
constexpr reference front() { return *data(); }
|
||||
constexpr const_reference front() const { return *data(); }
|
||||
constexpr reference back() { return *(data() + size() - 1); }
|
||||
constexpr const_reference back() const { return *(data() + size() - 1); }
|
||||
|
||||
// data access
|
||||
constexpr T* data() noexcept { return data_; }
|
||||
constexpr const T* data() const noexcept { return data_; }
|
||||
|
||||
constexpr reference push_back(const T& v)
|
||||
requires std::constructible_from<T, const T&>
|
||||
{
|
||||
return emplace_back(v);
|
||||
}
|
||||
|
||||
constexpr reference push_back(T&& v)
|
||||
requires std::constructible_from<T, T&&>
|
||||
{
|
||||
return emplace_back(std::forward<T&&>(v));
|
||||
}
|
||||
|
||||
template<typename... Args>
|
||||
requires(std::constructible_from<T, Args...>)
|
||||
constexpr T& unchecked_emplace_back(Args&&... args)
|
||||
{
|
||||
std::construct_at(end(), std::forward<Args>(args)...);
|
||||
++size_;
|
||||
return back();
|
||||
}
|
||||
|
||||
template<typename... Args>
|
||||
requires(std::constructible_from<T, Args...>)
|
||||
constexpr T* try_emplace_back(Args&&... args)
|
||||
{
|
||||
if (size() == capacity()) return nullptr;
|
||||
return &unchecked_emplace_back(std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template<typename... Args>
|
||||
requires std::constructible_from<T, Args...>
|
||||
constexpr reference emplace_back(Args&&... args)
|
||||
{
|
||||
MP_UNITS_EXPECTS(size() < capacity());
|
||||
auto ptr = try_emplace_back(std::forward<Args>(args)...);
|
||||
#if MP_UNITS_HOSTED
|
||||
if (!ptr) throw std::runtime_error("not enough capacity");
|
||||
#endif
|
||||
return *ptr;
|
||||
}
|
||||
|
||||
private:
|
||||
T data_[N];
|
||||
size_type size_ = 0;
|
||||
};
|
||||
|
||||
} // namespace mp_units::detail
|
||||
|
||||
// NOLINTEND(*-avoid-c-arrays)
|
Reference in New Issue
Block a user