473,386 Members | 1,715 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,386 software developers and data experts.

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 1184

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 thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

49
by: Ville Vainio | last post by:
I don't know if you have seen this before, but here goes: http://text.userlinux.com/white_paper.html There is a jab at Python, though, mentioning that Ruby is more "refined". -- Ville...
12
by: Frans Englich | last post by:
Hello, Since Python doesn't have static typing, how is the same result as traditional function overloads results in acheived? With function overloads the "selection of code path depending on...
68
by: Lad | last post by:
Is anyone capable of providing Python advantages over PHP if there are any? Cheers, L.
0
by: alainpoint | last post by:
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...
14
by: alainpoint | last post by:
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...
852
by: Mark Tarver | last post by:
How do you compare Python to Lisp? What specific advantages do you think that one has over the other? Note I'm not a Python person and I have no axes to grind here. This is just a question for...
30
by: Ivan Reborin | last post by:
Hello everyone, I was wondering if anyone here has a moment of time to help me with 2 things that have been bugging me. 1. Multi dimensional arrays - how do you load them in python For...
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.