#include #include #include #include #include "generator.h" // Universal allocator namespace memory { void* ptr{}; std::size_t n{}; } void* operator new(std::size_t n)// throw(std::bad_alloc) { std::cout << "new (" << n << " bytes from " << memory::ptr << " which is size " << memory::n << ")\n"; if(memory::ptr == nullptr) throw std::bad_alloc(); if(n > memory::n) throw std::bad_alloc(); auto ptr = memory::ptr; memory::ptr = nullptr; // use only once memory::n = 0; return ptr; } void operator delete(void*) throw() { std::cout << "delete\n"; // Do nothing. actual memory is allocated on the stack } void operator delete(void*, std::size_t) throw() { std::cout << "delete[]\n"; // Do nothing. actual memory is allocated on the stack } template class StackNew { public: StackNew() { std::cout << "StackNew ptr=" << (void*)buf << " of size " << S * sizeof(T) << '\n'; memory::ptr = buf; memory::n = S * sizeof(T); } private: T buf[S]; }; template Generator iota(T start) { while(true) { co_yield start++; } } int main() { std::cout << " ** std::string:\n"; { StackNew<100> buffer; std::string str{"hello allocating string world"}; try { str.reserve(50); // no stack buffer supplied so throws std::bad_alloc } catch(std::bad_alloc &e) { std::cout << "Stack buffer missing!\n"; } } std::cout << '\n'; std::cout << " ** std::vector:\n"; { StackNew<10, int> buffer; std::vector vec{1,2,3,4,5,6,7,8,9,10}; StackNew<20, int> buffer2; try { vec.resize(21); // throws std::bad_alloc } catch(std::bad_alloc &e) { std::cout << "Stack buffer was too small!\n"; } } std::cout << '\n'; std::cout << " ** std::function:\n"; { std::function f; { StackNew<32> buffer; char foo[32]{}; f = [foo]() { int i = 0; for(auto v : foo) { i += v; } return i; }; } [[maybe_unused]]auto x = f(); } std::cout << '\n'; std::cout << " ** co-routines:\n"; { StackNew<100> buffer; auto gen = iota(0); while(true) { auto i = gen(); if(i > 10) break; std::cout << i << " "; } std::cout << '\n'; } std::cout << '\n'; }