#include <iostream>
#include <stdexcept>

//
// Инфраструктура для работы с аренами.
//

// Интерфейс арены памяти.
// Вводится для того, чтобы можно было использовать один new с разными
// типами арен.
class memory_arena_t
   {
   public :
      virtual void *
      alloc( size_t object_size ) = 0;

      virtual bool
      has_enough_space( size_t object_size ) const = 0;
   };

// Реализация оператора new для работы с аренами памяти.
void *
operator new( size_t object_size, memory_arena_t & arena )
   {
      if( !arena.has_enough_space( object_size ) )
         throw std::bad_alloc();

      return arena.alloc( object_size );
   }

//
// Реализации конкретных типов арен.
//

// Арена памяти на основе статического блока фиксированного размера.
template< size_t CAPACITY >
class fixed_arena_t : public memory_arena_t
   {
   public :
      fixed_arena_t()
         :  pointer_( buffer_ )
         {}

      virtual void *
      alloc( size_t object_size )
         {
            void * result = pointer_;
            pointer_ += object_size;

            return result;
         }

      virtual bool
      has_enough_space( size_t object_size ) const
         {
            return ( pointer_ - buffer_ <= CAPACITY );
         }

   private :
      char buffer_[ CAPACITY ];
      char * pointer_;
   };

//
// Прикладная логика.
//

//
// Данные типы предназначены для размещения внутри арены.
// У них нет деструкторов, поскольку деструкторы все равно
// не будут вызываться.
//
struct first_child_t
   {
      int x_;
      int y_;
   };

struct second_child_t
   {
      int a_;
      int b_;
      int c_;
   };

struct owner_t
   {
      first_child_t * first_;
      second_child_t * second_;

      owner_t( first_child_t * first, second_child_t * second )
         :  first_( first )
         ,  second_( second )
         {}
   };

// Вот пример использования арены.
void
do_something_inside_arena( memory_arena_t & arena )
   {
      first_child_t * first = new(arena) first_child_t();
      second_child_t * second = new(arena) second_child_t();
      owner_t * owner = new(arena) owner_t( first, second );

      std::cout << "first: " << first
            << "\nsecond: " << second
            << "\nowner: " << owner
            << std::endl;
   }

int
main()
   {
      try
         {
            fixed_arena_t< 1024 > arena;
            do_something_inside_arena( arena );
         }
      catch( const std::exception & x )
         {
            std::cout << x.what() << std::endl;
         }
   }