omni/Vector.h
File members: omni/Vector.h
// Copyright (c) 2024, NVIDIA CORPORATION. All rights reserved.
//
// NVIDIA CORPORATION and its licensors retain all intellectual property
// and proprietary rights in and to this software, related documentation
// and any modifications thereto. Any use, reproduction, disclosure or
// distribution of this software and related documentation without an express
// license agreement from NVIDIA CORPORATION is strictly prohibited.
//
#pragma once
#include "detail/PointerIterator.h"
#include "detail/VectorDetail.h"
#include "../carb/Memory.h"
#include <memory>
namespace omni
{
template <class T>
class CARB_VIZ vector
{
public:
using value_type = T;
using allocator_type = typename ::carb::Allocator<T>;
using size_type = std::size_t;
using difference_type = std::ptrdiff_t;
using reference = value_type&;
using const_reference = const value_type&;
using pointer = typename std::allocator_traits<allocator_type>::pointer;
using const_pointer = typename std::allocator_traits<allocator_type>::const_pointer;
using iterator = detail::PointerIterator<pointer, vector>;
using const_iterator = detail::PointerIterator<const_pointer, vector>;
using reverse_iterator = std::reverse_iterator<iterator>;
using const_reverse_iterator = std::reverse_iterator<const_iterator>;
CARB_CPP20_CONSTEXPR vector() noexcept;
CARB_CPP20_CONSTEXPR explicit vector(const allocator_type&) noexcept : vector()
{
}
CARB_CPP20_CONSTEXPR vector(size_type count, const T& value, const allocator_type& alloc = allocator_type());
CARB_CPP20_CONSTEXPR vector(size_type count, const allocator_type& alloc = allocator_type());
template <class InputIt CARB_NO_DOC(, std::enable_if_t<detail::IsLegacyInputIterator<InputIt>::value, bool> = false)>
CARB_CPP20_CONSTEXPR vector(InputIt first, InputIt last, const allocator_type& = allocator_type())
{
_ranged_construct_or_reset(first, last, typename std::iterator_traits<InputIt>::iterator_category{});
}
CARB_CPP20_CONSTEXPR vector(const vector& other);
CARB_CPP20_CONSTEXPR vector(const vector& other, const allocator_type&) : vector(other)
{
}
CARB_CPP20_CONSTEXPR vector(vector&& other) noexcept;
CARB_CPP20_CONSTEXPR vector(vector&& other, const allocator_type&) noexcept : vector(std::move(other))
{
}
CARB_CPP20_CONSTEXPR vector(std::initializer_list<T> init, const allocator_type& alloc = allocator_type());
CARB_CPP20_CONSTEXPR ~vector();
CARB_CPP20_CONSTEXPR vector& operator=(const vector& other);
CARB_CPP20_CONSTEXPR vector& operator=(vector&& other) noexcept;
CARB_CPP20_CONSTEXPR vector& operator=(std::initializer_list<T> init);
CARB_CPP20_CONSTEXPR void assign(size_type count, const T& value);
template <class InputIt CARB_NO_DOC(, std::enable_if_t<detail::IsLegacyInputIterator<InputIt>::value, bool> = false)>
CARB_CPP20_CONSTEXPR void assign(InputIt first, InputIt last)
{
_ranged_assign(first, last, typename std::iterator_traits<InputIt>::iterator_category{});
}
CARB_CPP20_CONSTEXPR void assign(std::initializer_list<T> init);
CARB_CPP20_CONSTEXPR allocator_type get_allocator() const noexcept;
CARB_CPP20_CONSTEXPR reference at(size_type pos);
CARB_CPP20_CONSTEXPR const_reference at(size_type pos) const;
CARB_CPP20_CONSTEXPR reference operator[](size_type pos);
CARB_CPP20_CONSTEXPR const_reference operator[](size_type pos) const;
CARB_CPP20_CONSTEXPR reference front();
CARB_CPP20_CONSTEXPR const_reference front() const;
CARB_CPP20_CONSTEXPR reference back();
CARB_CPP20_CONSTEXPR const_reference back() const;
CARB_CPP20_CONSTEXPR pointer data() noexcept;
CARB_CPP20_CONSTEXPR const_pointer data() const noexcept;
CARB_CPP20_CONSTEXPR iterator begin() noexcept
{
return iterator(m_first);
}
CARB_CPP20_CONSTEXPR const_iterator begin() const noexcept
{
return const_iterator(m_first);
}
CARB_CPP20_CONSTEXPR const_iterator cbegin() const noexcept
{
return begin();
}
CARB_CPP20_CONSTEXPR iterator end() noexcept
{
return iterator(m_last);
}
CARB_CPP20_CONSTEXPR const_iterator end() const noexcept
{
return const_iterator(m_last);
}
CARB_CPP20_CONSTEXPR const_iterator cend() const noexcept
{
return end();
}
CARB_CPP20_CONSTEXPR reverse_iterator rbegin() noexcept
{
return std::make_reverse_iterator(end());
}
CARB_CPP20_CONSTEXPR const_reverse_iterator rbegin() const noexcept
{
return std::make_reverse_iterator(end());
}
CARB_CPP20_CONSTEXPR const_reverse_iterator crbegin() const noexcept
{
return rbegin();
}
CARB_CPP20_CONSTEXPR reverse_iterator rend() noexcept
{
return std::make_reverse_iterator(begin());
}
CARB_CPP20_CONSTEXPR const_reverse_iterator rend() const noexcept
{
return std::make_reverse_iterator(begin());
}
CARB_CPP20_CONSTEXPR const_reverse_iterator crend() const noexcept
{
return rend();
}
CARB_NODISCARD CARB_CPP20_CONSTEXPR bool empty() const noexcept;
CARB_NODISCARD CARB_CPP20_CONSTEXPR size_type size() const noexcept;
CARB_NODISCARD CARB_CPP20_CONSTEXPR size_type max_size() const noexcept;
CARB_CPP20_CONSTEXPR void reserve(size_type new_cap);
CARB_NODISCARD CARB_CPP20_CONSTEXPR size_type capacity() const noexcept;
CARB_CPP20_CONSTEXPR void shrink_to_fit();
CARB_CPP20_CONSTEXPR void clear() noexcept;
CARB_CPP20_CONSTEXPR iterator insert(const_iterator pos, const T& value);
CARB_CPP20_CONSTEXPR iterator insert(const_iterator pos, T&& value);
CARB_CPP20_CONSTEXPR iterator insert(const_iterator pos, size_type count, const T& value);
template <class Iter CARB_NO_DOC(, std::enable_if_t<detail::IsLegacyInputIterator<Iter>::value, bool> = false)>
CARB_CPP20_CONSTEXPR iterator insert(const_iterator pos, Iter first, Iter last)
{
return _ranged_insert(pos, first, last, typename std::iterator_traits<Iter>::iterator_category{});
}
CARB_CPP20_CONSTEXPR iterator insert(const_iterator pos, std::initializer_list<T> init);
template <class... Args>
CARB_CPP20_CONSTEXPR iterator emplace(const_iterator pos, Args&&... args);
CARB_CPP20_CONSTEXPR iterator erase(const_iterator pos);
CARB_CPP20_CONSTEXPR iterator erase(const_iterator first, const_iterator last);
CARB_CPP20_CONSTEXPR void push_back(const T& value);
CARB_CPP20_CONSTEXPR void push_back(T&& value);
template <class... Args>
CARB_CPP20_CONSTEXPR value_type& emplace_back(Args&&... args);
CARB_CPP20_CONSTEXPR void pop_back();
CARB_CPP20_CONSTEXPR void resize(size_type count);
CARB_CPP20_CONSTEXPR void resize(size_type count, const value_type& value);
CARB_CPP20_CONSTEXPR void swap(vector& other) noexcept;
private:
bool _has_unused_capacity() const noexcept;
size_type _unused_capacity() const noexcept;
void _move_from(vector&& other) noexcept;
size_type _calculate_growth(const size_type newSize) const;
bool _purchase(const size_type cap);
void _reset();
void _reset(const pointer newVec, const size_type newSize, const size_type newCapacity);
void _reallocate_exactly(const size_type newCapacity);
static allocator_type& _get_allocator() noexcept;
void _swap_all(vector&)
{
// Iterator debugging: Swap all iterators with another vector
}
void _orphan_all()
{
// Iterator debugging: all of our iterators are invalid
}
void _orphan_range(pointer, pointer)
{
// Iterator debugging: items in range (inclusive) are invalid
}
void _verify_iterator(const_iterator mine, bool allowEnd);
template <class Iter>
void _ranged_construct_or_reset(Iter first, Iter last, std::input_iterator_tag);
template <class Iter>
void _ranged_construct_or_reset(Iter first, Iter last, std::forward_iterator_tag);
template <class Iter>
void _ranged_assign(Iter first, Iter last, std::input_iterator_tag);
template <class Iter>
void _ranged_assign(Iter first, Iter last, std::forward_iterator_tag);
template <class Iter>
iterator _ranged_insert(const_iterator pos, Iter first, Iter last, std::input_iterator_tag);
template <class Iter>
iterator _ranged_insert(const_iterator pos, Iter first, Iter last, std::forward_iterator_tag);
template <class... Args>
value_type& _emplace_back_no_realloc(Args&&... args);
template <class... Args>
pointer _emplace_reallocate(const pointer where, Args&&... args);
template <class Pred>
void _internal_resize(const size_type count, Pred&& pred);
static void _impl_uninit_noexcept_move_or_copy(pointer first, pointer last, pointer dest, std::true_type);
static void _impl_uninit_noexcept_move_or_copy(pointer first, pointer last, pointer dest, std::false_type);
static void _uninit_noexcept_move_or_copy(pointer first, pointer last, pointer dest);
[[noreturn]] static void _length_error();
[[noreturn]] static void _range_error();
pointer m_first; // Beginning of array
pointer m_last; // End of array
pointer m_end; // End of allocated memory
};
template <class T>
CARB_NODISCARD inline bool operator==(const vector<T>& lhs, const vector<T>& rhs)
{
return (lhs.size() == rhs.size() && std::equal(lhs.begin(), lhs.end(), rhs.begin()));
}
template <class T>
CARB_NODISCARD inline bool operator!=(const vector<T>& lhs, const vector<T>& rhs)
{
return !(lhs == rhs);
}
template <class T>
CARB_NODISCARD inline bool operator<(const vector<T>& lhs, const vector<T>& rhs)
{
return std::lexicographical_compare(lhs.begin(), lhs.end(), rhs.begin(), rhs.end());
}
template <class T>
CARB_NODISCARD inline bool operator>(const vector<T>& lhs, const vector<T>& rhs)
{
return (rhs < lhs);
}
template <class T>
CARB_NODISCARD inline bool operator<=(const vector<T>& lhs, const vector<T>& rhs)
{
return !(rhs < lhs);
}
template <class T>
CARB_NODISCARD inline bool operator>=(const vector<T>& lhs, const vector<T>& rhs)
{
return !(lhs < rhs);
}
template <>
class vector<bool>
{
private:
vector() = default;
};
} // namespace omni
namespace std
{
template <class T>
void swap(omni::vector<T>& lhs, omni::vector<T>& rhs) noexcept
{
lhs.swap(rhs);
}
} // namespace std
CARB_INCLUDE_PURIFY_TEST({
using namespace omni;
vector<vector<int>> v(5);
vector<vector<int>> v2 = v;
v.assign(v2.begin(), v2.end());
v2.assign(5, {});
v2.assign({});
CARB_UNUSED(v.front(), v.back(), v.at(0), v[0], v.data(), v.cbegin(), v.cend(), v.rend(), v.rbegin(), v.crend());
CARB_UNUSED(v.crbegin(), v.empty(), v.size(), v.max_size(), v.capacity());
v.reserve(0);
v.shrink_to_fit();
v.clear();
v.insert(v.begin(), decltype(v)::value_type{});
v.insert(v.begin(), 5, decltype(v)::value_type{});
v.insert(v.begin(), v2.begin(), v2.end());
v.insert(v.begin(), std::initializer_list<decltype(v)::value_type>{});
v.emplace(v.begin(), 5);
v.erase(v.begin());
v2.erase(v2.begin(), v2.end());
v.push_back({});
v.pop_back();
v.resize(1);
v.resize(2, {});
v.swap(v2);
});
#if !defined __INTELLISENSE__
# include "Vector.inl"
#endif