// list_generator.h        -*-C++-*-
// -------------------------------------------------------
// Algorithm Library Design, Juha K"arkk"ainen, 06/06/2003
// A list generator described in
//   "Generative Programming: Methods, Tools, and Applications"
//   by Krzysztof Czarnecki and Ulrich W. Eisenecker
//   Addison-Wesley, 2000
// with minor changes.

#include "list_components.h"

//----------------------------------------------------------------------
// Meta IF
//----------------------------------------------------------------------

template <bool condition, class Then, class Else>
struct IF {
  typedef Then RET;
};

template <class Then, class Else>
struct IF<false, Then, Else> {
  typedef Else RET;
};

//----------------------------------------------------------------------
// Configuration DSL
//----------------------------------------------------------------------

enum Ownership {ext_ref, own_ref, cp};
enum Morphology {mono, poly};
enum CounterFlag {with_counter, no_counter};
enum TracingFlag {with_tracing, no_tracing};

//----------------------------------------------------------------------
// List generator
//----------------------------------------------------------------------

template <
  class       ElementType_,
  Ownership   ownership    = cp,
  Morphology  morphology   = mono,
  CounterFlag counter_flag = no_counter,
  TracingFlag tracing_flag = no_tracing,
  class       LengthType_  = int
>
class LIST_GENERATOR
{
public:

  // forward declaration of the configuration repository
  struct Config;

private:

  enum {
    is_copy      = ownership==cp,
    is_own_ref   = ownership==own_ref,
    is_mono      = morphology==mono,
    has_counter  = counter_flag==with_counter,
    does_tracing = tracing_flag==with_tracing 
  };

  typedef typename
  IF<is_copy || is_own_ref,
     ElementDestroyer<ElementType_>,
     EmptyDestroyer<ElementType_>
  >::RET Destroyer_;

  typedef typename
  IF<is_mono,
     DynamicTypeChecker<ElementType_>,
     EmptyTypeChecker<ElementType_>
  >::RET TypeChecker_;

  typedef typename
  IF<is_copy,
     typename 
     IF<is_mono,
	MonomorphicCopier<ElementType_>,
	PolymorphicCopier<ElementType_> >::RET,
     EmptyCopier<ElementType_>
  >::RET Copier_;

  typedef typename
  IF<is_copy,
     const ElementType_,
     ElementType_
  >::RET ElementArgumentType_;

  typedef PtrList<Config> BasicList;

  typedef typename
  IF<has_counter,
     LengthList<BasicList>,
     BasicList
  >::RET OptLengthList;

  typedef typename
  IF<does_tracing,
     TracedList<OptLengthList>,
     OptLengthList
  >::RET List;

public:

  typedef List RET;

  struct Config {
    typedef ElementType_           ElementType;
    typedef ElementArgumentType_   ElementArgumentType;
    typedef Copier_                Copier;
    typedef Destroyer_             Destroyer;
    typedef TypeChecker_           TypeChecker;
    typedef LengthType_            LengthType;

    typedef RET                    FinalListType;
  };

};




