#include <iostream>
#include <memory>

using namespace std;

template<typename BeingCounted>
class Counted


{
public:

class TooManyObjects
{};
static size_t getObjectsNum();

protected:
Counted();
Counted(Counted&);
~Counted();

private:
void init();

private:
static size_t numObjects;
static const size_t maxObjects;
};

template<typename BeingCounted>
size_t Counted<BeingCounted>::numObjects = 0;

template<typename BeingCounted>
size_t Counted<BeingCounted>::getObjectsNum()


{
return numObjects;
}

template<typename BeingCounted>
Counted<BeingCounted>::Counted()


{
init();
}

template<typename BeingCounted>
Counted<BeingCounted>::Counted(Counted&)


{
init();
}

template<typename BeingCounted>
Counted<BeingCounted>::~Counted()


{
--numObjects;
}

template<typename BeingCounted>
void Counted<BeingCounted>::init()


{
if( numObjects >= maxObjects )throw TooManyObjects();
++numObjects;
}

/**////////////////////////////////////////////////
class Printer:private Counted<Printer>


{
public:
using Counted<Printer>::getObjectsNum;
using Counted<Printer>::TooManyObjects;

public:

static Printer* make_aPrinter()
{return new Printer;}

static Printer* make_aCopy(const Printer& rhs)
{return new Printer(rhs);}

private:

Printer()
{}

Printer(const Printer& rhs)
{}
};

template<>
const size_t Counted<Printer>::maxObjects = 4;

int main()


{
try

{
auto_ptr<Printer> p1( Printer::make_aPrinter() );
auto_ptr<Printer> p2( Printer::make_aPrinter() );
auto_ptr<Printer> p3( Printer::make_aPrinter() );
auto_ptr<Printer> p5( Printer::make_aPrinter() );

cout << "current object number: "<< Printer::getObjectsNum() << endl;

auto_ptr<Printer> p4( Printer::make_aCopy( *p1 ) );
}
catch( Counted<Printer>::TooManyObjects& exp )

{
cout << "exception happened" << endl;
}

cout << "current object number: "<< Printer::getObjectsNum() << endl;
return 0;
}
