 // Purpose.  Composite                  // Strategy.  Use recursive composition
                                         // to create a heterogeneous aggregate
 #include <string.h>                     // that can be treated homogeneously.
 enum NodeType { FileT, DirT };          //
 int  g_indent = 0;                      // Benefit.  No more type checking and
                                         // type casting (coupling between Dir
 class File {                            // and File is gone, Dir is only
 public:                                 // coupled to abstract base class)
    File( char* n ) { type_ = FileT;
       strcpy( name_, n ); }             class AbsFile {
    NodeType getType() { return type_; } public:
    void ls() {                             virtual void ls() = 0;
       for (int i=0; i < g_indent; i++)  protected:
          cout << ' ';                      char        name_[20];
       cout << name_ << endl; }             static int  indent_;
 private:                                };
    NodeType  type_;                     int AbsFile::indent_ = 0;
    char      name_[20];
 };                                      class File: public AbsFile {
                                         public:
 class Dir {                                File( char* n ) {
 public:                                       strcpy( name_, n ); }
    Dir( char* n ) { type_ = DirT;          void ls() {
       strcpy( name_, n ); total_ = 0; }       for (int i=0; i < indent_; i++)
    NodeType getType() { return type_; }          cout << ' ';
    void add( File* f ) {                      cout << name_ << endl; }
       files_[total_++] = f;             };
    }
    void ls() {                          class Dir : public AbsFile {
       for (int i=0; i < g_indent; i++)  public:
          cout << ' ';                      Dir( char* n ) {
       cout << name_ << ":" << endl;           strcpy( name_, n ); total_ = 0; }
       g_indent += 3;                       void add( AbsFile* f ) {
       for (int i=0; i < total_; i++)          files_[total_++] = f; }
          if (files_[i]->getType()          void ls() {
                == DirT)                       for (int i=0; i < indent_; i++)
             ((Dir*) files_[i])->ls();            cout << ' ';
          else                                 cout << name_ << ":" << endl;
             files_[i]->ls();                  indent_ += 3;
       g_indent -= 3; }                        for (int i=0; i < total_; i++)
 private:                                         files_[i]->ls();
    NodeType  type_;                           indent_ -= 3; }
    char      name_[20];                 private:
    File*     files_[10];                   AbsFile*  files_[10];
    int       total_;                       int       total_;
 };                                      };

 void main( void )                       void main( void )
 {                                       {
    Dir   one("1"), two("2"), thr("3");     Dir   one("1"), two("2"), thr("3");
    File  a("a"), b("b"), c("c"),           File  a("a"), b("b"), c("c"),
          d("d"), e("e");                         d("d"), e("e");
    one.add( &a );                          one.add( &a );
    one.add( (File*) &two );                one.add( &two );
    one.add( &b );                          one.add( &b );
    two.add( &c );                          two.add( &c );
    two.add( &d );                          two.add( &d );
    two.add( (File*) &thr );                two.add( &thr );
    thr.add( &e );                          thr.add( &e );
    one.ls();                               one.ls();
 }                                       }

 // 1:          //       d               // 1:          //       d
 //    a        //       3:              //    a        //       3:
 //    2:       //          e            //    2:       //          e
 //       c     //    b                  //       c     //    b

