#pragma once #include #include namespace rng::util { template struct uninit final { inline static T* align_buffer(unsigned char* buffer) { return reinterpret_cast(buffer + alignof(T) - reinterpret_cast(buffer) % alignof(T)); } inline static const T* align_buffer(const unsigned char* buffer) { return reinterpret_cast(buffer + alignof(T) - reinterpret_cast(buffer) % alignof(T)); } inline T* ptr() { return align_buffer(&a_data[0]); } inline const T* ptr() const { return align_buffer(&a_data[0]); } inline unsigned char* bytes() { return &a_data[0]; } inline const unsigned char* bytes() const { return &a_data[0]; } inline uninit(T&& value) { give(std::move(value)); } inline uninit(){} inline void drop() { ptr()->~T(); } inline T&& take() { return std::move(*ptr()); } inline void give(T&& value) { new (ptr()) T(std::move(value)); } inline T& operator=(T&& value) { give(std::move(value)); return *ptr(); } inline T replace(T&& value) { auto x = take(); drop(); give(std::move(value)); return x; } inline static uninit move(uninit&& m) { return uninit(std::move(m)); } inline static uninit copy(const uninit& c) { return uninit(c); } inline uninit bitwise_copy() const { uninit u; u.a_data = a_data; return u; } private: inline uninit(const uninit& copy) : uninit(T(*copy.ptr())){} inline uninit(uninit&& move) : uninit(std::move(*move.ptr())){} std::array a_data; }; template struct generic_iterator { inline T try_next() { uninit v; if(next(v)) { return v.take(); } else throw "c++ sucks"; //XXX: eh... this is too draining } protected: virtual bool next(uninit& output) = 0; }; }