#include <stream.h>
#include "u.h"
#include "d.h"
#include "t.h"
#include "m.h"
#include "b.h"

main () {

    U *u = new U();
    U *w = new D();
    D *d = new D();
    T t;
    M m;
    B b;

    cout << "-- first test suite\n";
      u->cv(&t);
      u->cv(&m);
      u->cv(&b);
      //u->ctv(&t);
      cout<< "no matching function for call to `U::ctv (T *)' \n";
      //u->ctv(&m);
      cout<< "no matching function for call to `U::ctv (M *)' \n";
      u->ctv(&b);

    cout << "-- second test suite\n";
      //d->cv(&t);
      cout << "no matching function for call to `D::cv (T *)' \n";
      d->cv(&m);
      d->cv(&b);
      //d->ctv(&t);
      cout << " no matching function for call to `D::ctv (T *)' \n";
      d->ctv(&m);
      d->ctv(&b);

    cout << "-- third test suite\n";
      w->cv(&t);
      w->cv(&m);
      w->cv(&b);
      //w->ctv(&t);
      cout << "no matching function for call to `U::ctv (T *)'\n";
      //w->ctv(&m);
      cout << "no matching function for call to `U::ctv (M *)'\n";
      w->ctv(&b);
 };

// U class
// u.h
#ifndef _u
#define _u
#include "t.h"
#include "b.h"

class U
   {
   public:
     virtual void cv (T * t);
     virtual void ctv (B * b);
   };
#endif

// u.cpp
#include <stream.h>
#include "u.h"

void U :: cv (T * t)
      {
    cout << "cv(T) in U\n";
      }

void U :: ctv (B * b)
      {
    cout << "ctv(B) in U\n";
      }

// D class
// d.h
#ifndef _d
#define _d
#include "u.h"
#include "m.h"

class D : public U
   {
   public:
      virtual void cv (M * m); /* covariance */
      virtual void ctv (M * m); /* contravariance */
   };
#endif

// d.cpp
#include <stream.h>
#include "d.h"

void D :: cv (M * m) /* covariance */
      {
    cout << "cv(M) in D\n";
      }

void D :: ctv (M * m) /* contravariance */
      {
    cout << "ctv(M) in D\n";
      }

// T class
// t.h
#ifndef _t
#define _t

class T
   {
   };
#endif

// M class
// m.h
#ifndef _m
#define _m
#include "t.h"

class M : public T
   {
   };
#endif

// B class
// b.h
#ifndef _b
#define _b
#include "m.h"

class B : public M
   {
   };
#endif

// run
-- first test suite

cv(T) in U
cv(T) in U
cv(T) in U
no matching function for call to `U::ctv (T *)'
no matching function for call to `U::ctv (M *)'
ctv(B) in U

-- second test suite
no matching function for call to `D::cv (T *)'
cv(M) in D
cv(M) in D
no matching function for call to `D::ctv (T *)'
ctv(M) in D
ctv(M) in D

-- third test suite
cv(T) in U
cv(T) in U
cv(T) in U
no matching function for call to `U::ctv (T *)'
no matching function for call to `U::ctv (M *)'
ctv(B) in U