omni/detail/PointerIterator.h
File members: omni/detail/PointerIterator.h
// Copyright (c) 2021-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 "../../carb/Defines.h"
#include <iterator>
#include <type_traits>
#if CARB_HAS_CPP20 && defined(__cpp_concepts)
# include <concepts>
#endif
namespace omni
{
namespace detail
{
template <typename TPointer, typename TContainer>
class PointerIterator
{
static_assert(std::is_pointer<TPointer>::value, "TPointer must be a pointer type");
private:
using underlying_traits_type = std::iterator_traits<TPointer>;
public:
using value_type = typename underlying_traits_type::value_type;
using reference = typename underlying_traits_type::reference;
using pointer = typename underlying_traits_type::pointer;
using difference_type = typename underlying_traits_type::difference_type;
using iterator_category = typename underlying_traits_type::iterator_category;
#if CARB_HAS_CPP20 && defined(__cpp_concepts)
using iterator_concept = typename underlying_traits_type::iterator_concept;
#endif
public:
constexpr PointerIterator() noexcept : m_ptr{ nullptr }
{
}
explicit constexpr PointerIterator(pointer src) noexcept : m_ptr{ src }
{
}
PointerIterator(const PointerIterator&) = default;
PointerIterator(PointerIterator&&) = default;
PointerIterator& operator=(const PointerIterator&) = default;
PointerIterator& operator=(PointerIterator&&) = default;
~PointerIterator() = default;
// clang-format off
template <typename UPointer,
typename = std::enable_if_t
< !std::is_same<TPointer, UPointer>::value
&& std::is_convertible
<
std::remove_reference_t<typename PointerIterator<UPointer, TContainer>::reference>(*)[],
std::remove_reference_t<reference>(*)[]
>::value
>
>
constexpr PointerIterator(const PointerIterator<UPointer, TContainer>& src) noexcept
: m_ptr{src.operator->()}
{
}
// clang-format on
constexpr reference operator*() const noexcept
{
return *m_ptr;
}
constexpr reference operator[](difference_type idx) const noexcept
{
return m_ptr[idx];
}
constexpr pointer operator->() const noexcept
{
return m_ptr;
}
constexpr PointerIterator& operator++() noexcept
{
++m_ptr;
return *this;
}
constexpr PointerIterator operator++(int) noexcept
{
PointerIterator save{ *this };
++m_ptr;
return save;
}
constexpr PointerIterator& operator--() noexcept
{
--m_ptr;
return *this;
}
constexpr PointerIterator operator--(int) noexcept
{
PointerIterator save{ *this };
--m_ptr;
return save;
}
constexpr PointerIterator& operator+=(difference_type dist) noexcept
{
m_ptr += dist;
return *this;
}
constexpr PointerIterator operator+(difference_type dist) const noexcept
{
return PointerIterator{ m_ptr + dist };
}
constexpr PointerIterator& operator-=(difference_type dist) noexcept
{
m_ptr -= dist;
return *this;
}
constexpr PointerIterator operator-(difference_type dist) const noexcept
{
return PointerIterator{ m_ptr - dist };
}
private:
pointer m_ptr;
};
template <typename TPointer, typename TContainer>
inline constexpr PointerIterator<TPointer, TContainer> operator+(
typename PointerIterator<TPointer, TContainer>::difference_type dist,
const PointerIterator<TPointer, TContainer>& iter) noexcept
{
return iter + dist;
}
template <typename TPointer, typename UPointer, typename TContainer>
inline constexpr auto operator-(const PointerIterator<TPointer, TContainer>& lhs,
const PointerIterator<UPointer, TContainer>& rhs) noexcept
-> decltype(lhs.operator->() - rhs.operator->())
{
return lhs.operator->() - rhs.operator->();
}
template <typename TPointer, typename UPointer, typename TContainer>
inline constexpr bool operator==(const PointerIterator<TPointer, TContainer>& lhs,
const PointerIterator<UPointer, TContainer>& rhs) noexcept
{
return lhs.operator->() == rhs.operator->();
}
template <typename TPointer, typename UPointer, typename TContainer>
inline constexpr bool operator!=(const PointerIterator<TPointer, TContainer>& lhs,
const PointerIterator<UPointer, TContainer>& rhs) noexcept
{
return lhs.operator->() != rhs.operator->();
}
template <typename TPointer, typename UPointer, typename TContainer>
inline constexpr bool operator<(const PointerIterator<TPointer, TContainer>& lhs,
const PointerIterator<UPointer, TContainer>& rhs) noexcept
{
return lhs.operator->() < rhs.operator->();
}
template <typename TPointer, typename UPointer, typename TContainer>
inline constexpr bool operator<=(const PointerIterator<TPointer, TContainer>& lhs,
const PointerIterator<UPointer, TContainer>& rhs) noexcept
{
return lhs.operator->() <= rhs.operator->();
}
template <typename TPointer, typename UPointer, typename TContainer>
inline constexpr bool operator>(const PointerIterator<TPointer, TContainer>& lhs,
const PointerIterator<UPointer, TContainer>& rhs) noexcept
{
return lhs.operator->() > rhs.operator->();
}
template <typename TPointer, typename UPointer, typename TContainer>
inline constexpr bool operator>=(const PointerIterator<TPointer, TContainer>& lhs,
const PointerIterator<UPointer, TContainer>& rhs) noexcept
{
return lhs.operator->() >= rhs.operator->();
}
} // namespace detail
} // namespace omni