How do you implement this Python idiom in C++

alainpoint at yahoo.fr alainpoint at yahoo.fr
Sun Jul 30 13:21:09 EDT 2006


Pierre Barbier de Reuille wrote:
> alainpoint at yahoo.fr wrote:
> > Rob Williscroft wrote:
> >
> >> If this is more than idle curiosity I strongly suggest you post
> >> a version of the python code you need to translate to C++.
> >
> > For the moment this is just healthy curiosity but i will still post the
> > code i would like to see translated:
> >
> > class Parent:
> > 	count=0
> > 	def __init__(self):
> > 		self.__class__.count +=1
> > 	@classmethod
> > 	def getcount(cls):
> > 		return cls.count
> >
> > class Child(Parent):
> > 	count=0 # replace this line by a 'pass'  statement if you don't want
> > to reinitialise the count
> >
> > a=Parent()
> > b=Parent()
> > print Parent.getcount()  # you get 2
> > c=Child()
> > d=Child()
> > e=Child()
> > print Child.getcount() # you get 3 (you could get 5 if you don't
> > reinitialise the count)
> >
> > This is as simple as it can get. I just derive from Parent and i get my
> > proper count (added to my parent's if i wish so).
> > I wish i could achieve such a code purity in C++.
>
> Well, I hope you understand that this code "purity" is possible only
> because of the *dynamic* lookup of the variable name ... Thus, the same
> function, once compiled, will be able to determine, at runtime, where
> the current variable lies ... At the same time, tries, in Python, to
> achieve the count of *all* the instances of a class, meaning that you want :
>
> a = Parent()
> b = Child()
> c = Parent()
> d = Child()
> print Child.getcount() # 2
> print Parent.getcount() # 4
>
> That time, the automatic name lookup will come in the way as you cannot
> have two "count" variables accessible from the same class.
> For C++ the problem is inverse, you have a way to obtain the second
> thing (using templates or macro), but the first is harder.
>
> Pierre
>
> PS: here is my solution in C++
>
>
> #include <iostream>
> using namespace std;
>
> template <class T>
> struct Counted
> {
>   Counted() { ++count; }
>   Counted( Counted const& ) { ++count; }
>   virtual ~Counted() { --count; }
>   static size_t getCount() { return count; }
> protected:
>   static size_t count;
> };
>
> template <class T>
> size_t Counted<T>::count = 0;
>
> struct cA : public Counted<cA>
> {
>   int a;
> };
>
> struct cB : public Counted<cB>, public cA
> {
>   // Needed to be sure of which getCount is called in cB
>   using Counted<cB>::getCount;
> };
>
> int main()
> {
>   cA a,b,c;
>   cB d,e,f;
>   a.a = 1;
>   b.a = 1;
>   c.a = 1;
>   d.a = 1;
>   e.a = 1;
>   f.a = 1;
>     {
>     cA g;
>     g.a = 1;
>     cout << "#cA = " << cA::getCount() << endl; // 7
>     cout << "#cB = " << cB::getCount() << endl; // 3
>     }
>   cout << "#cA = " << cA::getCount() << endl; // 6
>   cout << "#cB = " << cB::getCount() << endl; // 3
>   return 0;
> }

I thank you for your response. The equivalent of your solution is
posted hereunder:
class cA(object):
        count=0
        def __init__(self):
                self.__class__.count +=1
        @classmethod
        def getcount(cls):
                return cls.count
	def __del__(self):
		self.__class__.count -=1
class cB(cA):
        count=0
        def __init__(self):
		super(cB,self).__init__()
		for klass in self.__class__.__bases__:
			klass.count +=1

a=cA() ; b=cA(); c= cA()
d=cB() ; e=cB(); f= cB()
a.a=1;b.a=1;c.a=1;d.a=1;e.a=1;f.a=1
g=cA()
g.a=1
print  '#cA=',cA.getcount()  # 7
print '#cB=',cB.getcount() #  3
del g
print  '#cA=',cA.getcount()  # 6
print '#cB=',cB.getcount() #  3

There is nothing impossible in Python ;-)

Alain




More information about the Python-list mailing list