#include <iostream>

using std::cerr;
using std::endl;

struct counter {};

struct foo : counter {};

struct bar
{
};

namespace auto_ptr_impl
{
  template <typename x>
  x test (...);

  template <typename>
  counter test (counter*);

  template <typename x>
  struct type
  {
    typedef typeof (test<x> (reinterpret_cast<x*> (0))) r;
  };

  template <typename x>
  struct cmu
  {
    cmu ()
    {
      cerr << "using non-invasive ref counter" << endl;
    }
  };

  template <>
  struct cmu<counter>
  {
    cmu ()
    {
      cerr << "using invasive ref counter of type 'counter'" << endl;
    }
  };
}


template <typename x>
struct auto_ptr
{
  auto_ptr_impl::cmu<typename auto_ptr_impl::type<x>::r> cmu_;
};

struct my_counter {};

struct taz : my_counter {};


namespace auto_ptr_impl
{
  template <typename>
  my_counter test (my_counter*);

  template <>
  struct cmu<my_counter>
  {
    cmu ()
    {
      cerr << "using invasive ref counter of type 'my_counter'" << endl;
    }
  };
}

struct fwd;

typedef auto_ptr<fwd> fwd_ptr;

struct fwd : counter
{
  fwd_ptr foo ()
  {
    return fwd_ptr ();
  }
};


int
main ()
{
  auto_ptr<int> ip;
  auto_ptr<bar> bp;

  auto_ptr<counter> cp;
  auto_ptr<foo> fp;

  auto_ptr<my_counter> mp;
  auto_ptr<taz> tp;

  fwd fwd;
  fwd_ptr fwdp = fwd.foo ();
}
