FIXED-SIZE-CONTAINERS FOR C++
------------------------------

  This is an experimental implementation of two STL-like containers
  with fixed memory allocation, fixed_vector and fixed_list.

  These containers never allocate memory. They exclusively use a block
  of memory assigned to them at construction time; an attempt to
  overflow that memory block yields a fixed_container_overrun
  exception. This way, you can easily assign fixed memory blocks,
  which is useful not only in embedded systems.


Usage
------

  ----8<--------8<--------8<--------8<--------8<--------8<--------8<----
  #include "fixed_vector.h"

  class Foo { ... };

  int compute_count();

  enum { COUNT = 20 };

  /* allocation of a separate memory block (could be a linker memory
     reservation or something like that). You have to make sure alignment
     is right. */
  char the_buffer[COUNT * fixed_vector<Foo>::node_size];
  fixed_vector<Foo> vec1(the_buffer, COUNT);

  /* allocation of the required memory directly in the vector object */
  static_vector<Foo,COUNT> vec2;

  /* allocation of the required memory from the heap */
  heap_vector<Foo> vec3(compute_count());
  ----8<--------8<--------8<--------8<--------8<--------8<--------8<----

  fixed_list is used in a similar way.

  All containers come in three flavours:

  - fixed_XXX: this is the raw container. It does no memory
    management, just the container. Constructors are the same as for
    std::vector, and get two additional arguments: the data pointer
    and the desired number of elements. You have to make sure that the
    data pointer is sufficiently aligned and points to enough space.

  - static_XXX: contains the actual data within the object, and can
    thus have a copy constructor and otherwise constructors that are
    completely compatible to those of std::vector. Con: upper bound is
    a compile-time constant.

  - heap_XXX: allocates the data from the heap. Pro: upper bound need
    not be known until construction time. Con: heap allocation.

  All containers export a static const 'node_size' which is the amount
  of memory required to hold one value. Use this to compute the amount
  of memory required for the container, or the number of elements that
  fit in a given size.

  static_XXX and heap_XXX are derived from fixed_XXX, so code written
  to accept fixed_XXX& will work with all of them.

  Otherwise, the containers are used exactly like their std::
  counterparts (i.e. begin(), size(), at(), push_back() etc). The only
  differences are that there is no reserve(), and that they throw
  fixed_container_overrun when you attempt to exceed the predefined
  size.


Todo
-----

  fixed_list does not yet have splice(). What semantics should it
  have? Can we support splicing elements from one list into another
  without copying? (Elements would then die when the other list dies.)

  When should overruns be detected? Some operations are partially
  performed before the error is detected.

  Possibly make error reporting configurable (embedded platforms may
  not have exceptions).

  Make the static_XXX / heap_XXX into templates, i.e.
  'static_container<fixed_list<int>,10>'.

  Add fixed_map / fixed_set.

  Add fixed_queue. Can be done with fixed_list already, but we can do
  much more efficient using a ring buffer (no need for the link
  pointers). A fixed_stack is not needed, fixed_vector is good enough.

  iterator / const_iterator conversions for fixed_list do not yet work.

  Add fixed_slist? fixed_string?

  Should heap_XXX() have a copy constructor?

  Small lists do not need two full pointers for linkage.

  Instead of 'throw fixed_container_overrun', use into a template
  argument to decide the behaviour. Ultimately, this would even allow
  building std::vector from fixed_vector.


Author
-------

  Stefan Reuther <Streu@gmx.de>

  Share and enjoy.
