Created
November 15, 2022 09:10
-
-
Save CyberDNIWE/c806ad3814ed7764f1537296a8a39e2f to your computer and use it in GitHub Desktop.
poorly::Iterable, make plain-c arrays "poorly" iterable
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// poorly::Iterable: poor man's iterator provider that does not take ownership of underlying array | |
// Usage: copy-paste poorly namespace & use MAKE_POORLY_ITERABLE to make plain-c array iterable. | |
// (see examples for more info). | |
#pragma region COPY_PASTE_ITERABLE | |
#include <cstdint> | |
namespace poorly | |
{ | |
template<typename T, size_t SIZE> | |
struct Iterable | |
{ | |
using ConstPtr = T * const; | |
struct iterator | |
{ | |
public: | |
constexpr iterator() noexcept : ptr(nullptr) | |
{} | |
constexpr iterator(T* p) noexcept : ptr(p) | |
{} | |
void begin(const Iterable& v) noexcept | |
{ | |
ptr = v.m_dataPtr; | |
} | |
T& operator*() const noexcept | |
{ | |
return *ptr; | |
} | |
const iterator& operator++() noexcept | |
{ | |
++ptr; | |
return *this; | |
} | |
bool operator != (const iterator& other) const noexcept | |
{ | |
return ptr != other.ptr; | |
} | |
private: | |
T* ptr; | |
}; | |
public: | |
constexpr Iterable(ConstPtr first) : m_dataPtr(first) | |
{} | |
constexpr iterator begin() const | |
{ | |
return { m_dataPtr }; | |
} | |
constexpr const iterator end() const | |
{ | |
return { m_dataPtr + SIZE }; | |
} | |
private: | |
ConstPtr m_dataPtr = nullptr; | |
}; | |
// These are here to deduce underlying types in case some wise guy decides to use mutlidim arrays | |
template<class T> | |
struct remove_all_extents | |
{ typedef T type; }; | |
template<class T> | |
struct remove_all_extents<T[]> | |
{ typedef typename remove_all_extents<T>::type type; }; | |
template<class T, size_t N> | |
struct remove_all_extents<T[N]> | |
{ typedef typename remove_all_extents<T>::type type; }; | |
template<typename T, size_t SIZE> | |
constexpr size_t array_length(T(&)[SIZE]) { return SIZE; } | |
#ifndef MAKE_POORLY_ITERABLE | |
#define MAKE_POORLY_ITERABLE(arrname) poorly::Iterable<remove_all_extents<decltype(arrname)>::type, poorly::array_length(arrname)>(arrname) | |
#endif | |
}; | |
#pragma endregion | |
#pragma region ints | |
#define A_FEW_TIMES size_t i = 0; i < 2; ++i | |
using namespace poorly; | |
constexpr int arr[] = { 1,2,3,4,5 }; | |
void testWithInts() noexcept | |
{ | |
auto iteratable = MAKE_POORLY_ITERABLE(arr); | |
///* | |
// Simple ranged for | |
for(const auto& v : iteratable) | |
{ | |
int cur = v; | |
bool dbg3 = true; | |
} | |
//*/ | |
// Create once, reuse multiple times- iterator approach | |
auto iter1 = iteratable.begin(); | |
auto iter2 = iteratable.end(); | |
for(A_FEW_TIMES) | |
{ | |
for(; iter1 != iter2; ++iter1) | |
{ | |
const int& cur = *iter1; | |
bool dbg3 = true; | |
} | |
//Reset iter1 without re-constructing | |
iter1.begin(iteratable); | |
} | |
} | |
#pragma endregion | |
#pragma region inheritance | |
// Stuff to test out class chierarcies | |
#pragma region stufftotestout | |
struct Base | |
{ | |
constexpr Base() noexcept = default; | |
virtual ~Base() = default; | |
virtual void doStuff() const noexcept = 0; | |
}; | |
class Derived : public Base | |
{ | |
public: | |
Derived() noexcept = default; | |
~Derived() = default; | |
virtual void doStuff() const noexcept; | |
private: | |
}; | |
#include <iostream> | |
void Derived::doStuff() const noexcept | |
{ | |
std::cout << "Derived::doStuff() called" << '\n'; | |
} | |
class OtherDerived : public Base | |
{ | |
public: | |
constexpr OtherDerived() noexcept = default; | |
~OtherDerived() = default; | |
virtual void doStuff() const noexcept; | |
private: | |
}; | |
void OtherDerived::doStuff() const noexcept | |
{ | |
std::cout << "OtherDerived::doStuff() called" << '\n'; | |
} | |
#pragma endregion | |
const Derived foo = {}; | |
const OtherDerived bar = {}; | |
const OtherDerived bar2 = {}; | |
constexpr const Base* things[] = { &foo, &bar, &bar2 }; | |
void testWithRuntumePolymorphism() noexcept | |
{ | |
auto iterable = MAKE_POORLY_ITERABLE(things); | |
// Simple ranged for | |
for(const auto& thing : things) | |
{ | |
thing->doStuff(); | |
} | |
std::cout << '\n'; | |
// Create once, use multiple times approach | |
auto cur = iterable.begin(); | |
const auto end = iterable.end(); | |
for(A_FEW_TIMES) | |
{ | |
for(; cur != end; ++cur) | |
{ | |
(*cur)->doStuff(); | |
} | |
cur.begin(iterable); | |
std::cout << '\n'; | |
} | |
} | |
#pragma endregion | |
int main() | |
{ | |
///* | |
testWithInts(); | |
//*/ | |
///* | |
testWithRuntumePolymorphism(); | |
//*/ | |
std::getchar(); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment