468,497 Members | 1,875 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 468,497 developers. It's quick & easy.

How do you implement this Python idiom in C++

Hello,

I have the need to write the equivalent of Python class methods in C++.

Chuck Allison proposes the following
(http://www.artima.com/cppsource/simple.html):
#include <iostream>
using namespace std;

// A base class that provides counting
template<class Tclass Counted {
static int count;
public:
Counted() { ++count; }
Counted(const Counted<T>&) { ++count; }
~Counted() { --count; }
static int getCount() { return count; }

};

template<class Tint Counted<T>::count = 0;

// Curious class definitions
class CountedClass : public Counted<CountedClass{};
class CountedClass2 : public Counted<CountedClass2{};

It apparently works but in fact it doesn't:
If you derive from such a class, you get the count of the parent class,

not of the derived class.
class CountedClass3 : public CountedClass {};

int main() {
CountedClass a;
cout << CountedClass::getCount() << endl; // 1
CountedClass b;
cout << CountedClass::getCount() << endl; // 2
CountedClass3 c;
cout << CountedClass3::getCount() << endl; // 3 and should be 1
cout << CountedClass::getCount() << endl; // 3 and should be 2

}

I am no C++ expert but i guess there might be some in the Python and
C++ newsgroups.

Alain

Jul 27 '06 #1
14 1055

al********@yahoo.fr wrote:
// Curious class definitions
class CountedClass : public Counted<CountedClass{};
class CountedClass2 : public Counted<CountedClass2{};

It apparently works but in fact it doesn't:
If you derive from such a class, you get the count of the parent class,

not of the derived class.
class CountedClass3 : public CountedClass {};
Hint: where's the template parameter gone as per the previous two
statements...

Jon.

Jul 27 '06 #2
al********@yahoo.fr wrote:
Hello,

I have the need to write the equivalent of Python class methods in C++.

Chuck Allison proposes the following
(http://www.artima.com/cppsource/simple.html):
#include <iostream>
using namespace std;

// A base class that provides counting
template<class Tclass Counted {
static int count;
public:
Counted() { ++count; }
Counted(const Counted<T>&) { ++count; }
~Counted() { --count; }
static int getCount() { return count; }

};

template<class Tint Counted<T>::count = 0;

// Curious class definitions
class CountedClass : public Counted<CountedClass{};
class CountedClass2 : public Counted<CountedClass2{};

It apparently works but in fact it doesn't:
If you derive from such a class, you get the count of the parent class,

not of the derived class.
class CountedClass3 : public CountedClass {};

int main() {
CountedClass a;
cout << CountedClass::getCount() << endl; // 1
CountedClass b;
cout << CountedClass::getCount() << endl; // 2
CountedClass3 c;
cout << CountedClass3::getCount() << endl; // 3 and should be 1
cout << CountedClass::getCount() << endl; // 3 and should be 2

}

I am no C++ expert but i guess there might be some in the Python and
C++ newsgroups.

Alain
Why don't you post the Python code you want to "translate" ? Here, I
just don't know what you want to achieve !!

Pierre
Jul 27 '06 #3

Jon Clements wrote:
al********@yahoo.fr wrote:
// Curious class definitions
class CountedClass : public Counted<CountedClass{};
class CountedClass2 : public Counted<CountedClass2{};

It apparently works but in fact it doesn't:
If you derive from such a class, you get the count of the parent class,

not of the derived class.
class CountedClass3 : public CountedClass {};

Hint: where's the template parameter gone as per the previous two
statements...

Jon.
You miss the point; i want to derive a class and inherit all properties
without worrying about those implementation details. The Python code is
much cleaner in that respect. My post is about whether it is possible
to get such a clean interface in C++

Alain

Jul 27 '06 #4

alainpo...@yahoo.fr wrote:
You miss the point; i want to derive a class and inherit all properties
without worrying about those implementation details. The Python code is
much cleaner in that respect. My post is about whether it is possible
to get such a clean interface in C++
I was simply pointing out that your statement declaring that it didn't
work, wasn't accurate, because the code you'd used was incorrect.

Jon

Jul 27 '06 #5

al********@yahoo.fr wrote:
I am no C++ expert but i guess there might be some in the Python and
C++ newsgroups.
Provide compilable code that exibits your problem. The technique is
sound; you must be screwing up somehow.
#include <iostream>

using namespace std;

template <typename T>
class counted
{
static int count;

public:
counted() { ++ count; }
counted(const counted<T&) { ++ count; }
virtual ~counted() { -- count; }
static int getCount() { return count; }
};

template <typename T>
int counted<T>::count = 0;

class C1 : public counted<C1>
{
public:
C1() : counted() {}
};

class C2 : public counted<C2>
{
public:
C2() : counted() {}
};

int main(void)
{
C1 c11;
C1 c12;
C2 c2;

cout << C1::getCount() << endl;
cout << C2::getCount() << endl;

int c;
cin >c;

return 0;
}
output is 2 and 1 as expected. Removing the constructors in the
derivatives doesn't change that fact.

Jul 27 '06 #6
wrote in news:11*********************@i42g2000cwa.googlegro ups.com in
comp.lang.python:
#include <iostream>
using namespace std;

// A base class that provides counting
template<class Tclass Counted {
static int count;
};

template<class Tint Counted<T>::count = 0;

// Curious class definitions
class CountedClass : public Counted<CountedClass{};
class CountedClass2 : public Counted<CountedClass2{};

It apparently works but in fact it doesn't:
If you derive from such a class, you get the count of the parent class,
You are mistaken about how it should work in the first place.
It may well be that it doesn't do what you wan't it to.

To translate the python idom into C++ you need to replace
derivation with the CRTP (*) code the author supplied.

*) CRTP = Curiosly Recuring Template Pattern
>
not of the derived class.
class CountedClass3 : public CountedClass {};
Don't use the above always use:

class CountedClass3 : public Counted< CountedClass3 >
{
};

Note that the "classmethod emulation" stops here, if you need
it to continue you will need to keep using the CRTP:

template < typename T = void >
class CountedClass : public Counted< CountedClass< T
{
};

Create instances:

CountedClass<cc; /* T = void */

Derive (keeping the "classmethod emulation") using the CRTP:

template < typename T = void /* So we can "Derive" again */
class CountedClass2 : public CountedClass< CountedClass2< void
{
};

Note that the trick works by always making the instantition of
Counted< T you are deriving from unique, CountedClass<has
a base class Counted< CountedClass< void and CountedClass2<>
has (ultimatly) a base class Counted< CountedClass2< void .

Ofcouse the next problem is that CRTP-derivation above isn't real
derivation, this idom translation clearly has a breaking point.

If this is more than idle curiosity I strongly suggest you post
a version of the python code you need to translate to C++.

Rob.
--
http://www.victim-prime.dsl.pipex.com/
Jul 27 '06 #7
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++.

Alain

Jul 27 '06 #8

al********@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)
What happens if you print Parent.getcount() now?

Jul 27 '06 #9

Noah Roberts wrote:
What happens if you print Parent.getcount() now?
You still get 2 since there is no new instance of Parent that was
created.

Alain

Jul 27 '06 #10
al********@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;
}
Jul 28 '06 #11

Pierre Barbier de Reuille wrote:
al********@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

Jul 30 '06 #12
al********@yahoo.fr wrote:
Pierre Barbier de Reuille wrote:
[...]
>
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
Well, nothing is impossible, but it is now much much more complex ! As a
proof of that, your version does not work completely :P (try deleting d
for example).

I add a working version, but you will also notice that I have to
*explicitly* walk over all the classes of the hierarchy, testing for the
one who have a "count" attribute, hoping that this attribute is indeed
for counting the number of objects and not anything else ... so the
solution is quite fragile and very slow.

class cA(object):
count=0
def __init__(self):
self.__class__.count +=1
for klass in self.__class__.__bases__:
if hasattr( klass, "count" ):
klass.count += 1

@classmethod
def getcount(cls):
return cls.count
def __del__(self):
self.__class__.count -=1
for klass in self.__class__.__bases__:
if hasattr( klass, "count" ):
klass.count -= 1
class cB(cA):
count=0

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
del d
print '#cA=',cA.getcount() # 5
print '#cB=',cB.getcount() # 2

Pierre
Jul 30 '06 #13

Pierre Barbier de Reuille wrote:
al********@yahoo.fr wrote:
Pierre Barbier de Reuille wrote:
[...]

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

Well, nothing is impossible, but it is now much much more complex ! As a
proof of that, your version does not work completely :P (try deleting d
for example).

I add a working version, but you will also notice that I have to
*explicitly* walk over all the classes of the hierarchy, testing for the
one who have a "count" attribute, hoping that this attribute is indeed
for counting the number of objects and not anything else ... so the
solution is quite fragile and very slow.

class cA(object):
count=0
def __init__(self):
self.__class__.count +=1
for klass in self.__class__.__bases__:
if hasattr( klass, "count" ):
klass.count += 1

@classmethod
def getcount(cls):
return cls.count
def __del__(self):
self.__class__.count -=1
for klass in self.__class__.__bases__:
if hasattr( klass, "count" ):
klass.count -= 1
class cB(cA):
count=0

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
del d
print '#cA=',cA.getcount() # 5
print '#cB=',cB.getcount() # 2

Pierre
Good point Pierre. But you'll have to admit that the class usage in
Python is much simpler (just derive from the class)
class cB(cA):
count=0
contrarily to the C++ usage where you must remind the compiler of the
Counted class in every derived class.

In Python, you have to bite only once thru the sour apple ....
Alain

Jul 31 '06 #14
You are heading the wrong way...

There are a number of ways to implement this but the easiest I can think
of is to use RTTI.

To get around with counting sub-objects you can rely on virtual
inheritance, which only happens at the top of the inheritance tree.

Here is a simple demo:

#include <iostream>
#include <typeinfo>
#include <map>

class count
{
public:
typedef std::map<const std::type_info*, unsigned intcounts_t;
static counts_t counts;

const std::type_info* ti;

static unsigned int get_count(const std::type_info& c)
{return counts[&c];}

count(const std::type_info& c):ti(&c){++counts[ti];}
~count(){--counts[ti];}
};

count::counts_t count::counts;

class c1: virtual private count
{
public: c1(): count(typeid(c1)){}
};

class c2: public c1, virtual private count
{
public: c2(): count(typeid(c2)){}
};

int main()
{
c1 t1[3];
c2 t2[5];

std::cout << count::get_count(typeid(c1)) << "\n";
<< count::get_count(typeid(c2)) << "\n";

return 0;
}
Jul 31 '06 #15

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

12 posts views Thread by Frans Englich | last post: by
68 posts views Thread by Lad | last post: by
reply views Thread by alainpoint | last post: by
14 posts views Thread by alainpoint | last post: by
852 posts views Thread by Mark Tarver | last post: by
30 posts views Thread by Ivan Reborin | last post: by
reply views Thread by NPC403 | last post: by
3 posts views Thread by gieforce | last post: by
By using this site, you agree to our Privacy Policy and Terms of Use.