Add srb2::MobjListView: container view, which can iterate a mobj-pointer linked list by calling a lambda

This commit is contained in:
James R 2023-11-27 05:07:10 -08:00
parent b4be1d5e9c
commit 548618a238

74
src/mobj_list_view.hpp Normal file
View file

@ -0,0 +1,74 @@
// DR. ROBOTNIK'S RING RACERS
//-----------------------------------------------------------------------------
// Copyright (C) 2023 by James Robert Roman
//
// This program is free software distributed under the
// terms of the GNU General Public License, version 2.
// See the 'LICENSE' file for more details.
//-----------------------------------------------------------------------------
#ifndef mobj_list_view_hpp
#define mobj_list_view_hpp
#include <cstddef>
#include <iterator>
#include <type_traits>
#include "mobj.hpp"
namespace srb2
{
// for (T* ptr : MobjList(hnext(), [](T* ptr) { return ptr->hnext(); }))
template <typename T, typename F, std::enable_if_t<std::is_convertible_v<T, Mobj>, bool> = true>
struct MobjListView
{
struct Iterator
{
using iterator_category = std::forward_iterator_tag;
using difference_type = std::ptrdiff_t;
using value_type = T*;
using pointer = value_type;
using reference = value_type;
Iterator(pointer ptr, F adv) : ptr_(deref(ptr)), adv_(adv) {}
bool operator==(const Iterator& b) const { return ptr_ == b.ptr_; };
bool operator!=(const Iterator& b) const { return ptr_ != b.ptr_; };
reference operator*() const { return ptr_; }
pointer operator->() { return &ptr_; }
Iterator& operator++()
{
ptr_ = deref(adv_(ptr_));
return *this;
}
Iterator operator++(int)
{
Iterator prev = *this;
++(*this);
return prev;
}
private:
pointer ptr_;
F adv_;
static T* deref(T* ptr) { return ptr && ptr->valid() ? ptr : nullptr; }
};
MobjListView(T* ptr, F adv) : ptr_(ptr), adv_(adv) {}
Iterator begin() const { return {ptr_, adv_}; }
Iterator end() const { return {nullptr, adv_}; }
private:
T* ptr_;
F adv_;
};
}; // namespace srb2
#endif/*mobj_list_view_hpp*/