Sign in to follow this  
The C modest god

Adding a feature to CPP

Recommended Posts

I thought it would be nice if you could define your own recursive method. It will be just like a dtr. Lets call this methos Recur Every class will have the default Recur which will only call the Recur of all its class members. You will able to overide this method in every specific class. Its a great feature that could enhance CPP. What do you think?

Share this post


Link to post
Share on other sites
I think what you're asking is if you can modify how classes are defined in C++, i.e. add this "Recur" method to the standard interface of a class much like every class can (and should) define a constructor/destructor, this "Recur" method would be another addition to the way we commonly define classes.

Now, this is a big assumption because I really am not sure what you're asking, but if this is what you're asking then I'll have to tell you that you can't really change the way classes are understood to be, or interpreted in C++, but with _very_ good reason. The language was given much thought when it was developed and has fairly standard procedures for adding new features AFAIK.

To me though, and this is partly due to the fact I really don't know what you're talking about, this doesn't really sound like a necessary or even good addition to the language. I have never found the need for such an addition to the way classes work in C++, and as of yet you've failed to convince me otherwise (again, specifically because what you're saying is fairly unclear).

Care to explain a little more?

Share this post


Link to post
Share on other sites
What is the standard procedure to add such a feature?

Well, I am making my own memory management.
CPP does not have reasonable support or any language support to multi threading, so how can you say nothing is missing in this language?

The thing is, I want to "cunurrently" relase several heap allocated objects.
These objects may have reference pointers to each other, maybe even in a circle.
So I need to first release the references pointers before actually deleteing the data, so I wont have a dangling reference or something like this.
I could simply right for every class a method that will call all the sub classes methods of the same method that its purpose is to release there reference pointers.
But I would rather have some sort of a recursive method like the dstr.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
Quote:
Original post by The C modest god
What is the standard procedure to add such a feature?

Well, I am making my own memory management.
CPP does not have reasonable support or any language support to multi threading, so how can you say nothing is missing in this language?

The thing is, I want to "cunurrently" relase several heap allocated objects.
These objects may have reference pointers to each other, maybe even in a circle.
So I need to first release the references pointers before actually deleteing the data, so I wont have a dangling reference or something like this.
I could simply right for every class a method that will call all the sub classes methods of the same method that its purpose is to release there reference pointers.
But I would rather have some sort of a recursive method like the dstr.


in case that you should actually consider suggesting whatever you are describing here for the upcoming version of C++0x, you might also want to seriously consider reading up on grammar and spelling, as you might then have better chances to be taken seriously then.

Also, the proper "procedure" to discuss potential language enhancements for C++, is to discuss your ideas in comp.lang.c++ (usenet newsgroup). Un general, it is a good idea to provide real life case examples for why your suggestion might be useful.

On the other hand, suggestions for language enhancements are usually only taken seriously if they come from people who are INHERENTLY familiar with the language itself, you-as someone who has obviously just started to learn it- might rather want to get more familiar with it, before riskiing to be flamed for making a totally incomprehensible and possibly even idiotic "suggestion".


Share this post


Link to post
Share on other sites
Quote:
Original post by The C modest god
Is there a book on the internal of CPP?
Like all the VTables?
Perhaps resources on the internet?


No, because the internal of C++ (ie its implementation) is compiler dependant. The compiler vendor decides how it deals with such issue, and there is no standard that describe them. A vendor may find a way to represent vtables that doesn't add any overhead to the class, while another one might decide to add a hidden pointer in the class.

Going back to your original question (and when I say original, I really mean original), what makes you think that such feature is useful? How would it be used? Does an int have a "default Recur"? I still don't get your point (and even if I understood you, I'll tell you that Recur is really a poor name). Can you detail this? (not by throwing 3 words in a post: try to be more formal).

BTW, multi-threading support is not done by the language - it is done by a library so you can use it if you want, and forget it if you don't want it (adding 0 overhead in this case). This is the philosophy of the language: you pay for what you use.

Regards,

Share this post


Link to post
Share on other sites
Quote:
Original post by Anonymous Poster
Quote:
Original post by The C modest god
What is the standard procedure to add such a feature?

Well, I am making my own memory management.
CPP does not have reasonable support or any language support to multi threading, so how can you say nothing is missing in this language?

The thing is, I want to "cunurrently" relase several heap allocated objects.
These objects may have reference pointers to each other, maybe even in a circle.
So I need to first release the references pointers before actually deleteing the data, so I wont have a dangling reference or something like this.
I could simply right for every class a method that will call all the sub classes methods of the same method that its purpose is to release there reference pointers.
But I would rather have some sort of a recursive method like the dstr.


in case that you should actually consider suggesting whatever you are describing here for the upcoming version of C++0x, you might also want to seriously consider reading up on grammar and spelling, as you might then have better chances to be taken seriously then.

Also, the proper "procedure" to discuss potential language enhancements for C++, is to discuss your ideas in comp.lang.c++ (usenet newsgroup). Un general, it is a good idea to provide real life case examples for why your suggestion might be useful.

On the other hand, suggestions for language enhancements are usually only taken seriously if they come from people who are INHERENTLY familiar with the language itself, you-as someone who has obviously just started to learn it- might rather want to get more familiar with it, before riskiing to be flamed for making a totally incomprehensible and possibly even idiotic "suggestion".

Why did you use Un? Is your reply not proper now?

I will give you an example:


class SubCounter {
public:
int num;
SubCounter() { this->num = 0; };
void Initiate ()
{
this->num=0;
};
};

class Counter {
public:
int num;
SubCounter ctr;
Counter() { this->num = 0; };
void Initiate ()
{
this->num=0;
ctr.Initaite();
};
};

class SuperCounter {
public:
int num;
Counter ctr;
SuperCounter() { this->num = 0; };
void Initiate ()
{
this->num=0;
ctr.Initaite();
};
};

SuperCounter var;




var will be constructed and all the ints inside it will be set to 0.
I have used var somehow and changed the values of num within it, to values different from 0.
Now I need to use another SuperCounter.
I don't need to use var anymore, so I could reuse var instead of having another variable in the stack or using heap allocated instance of SuperCounter.
I need this SuperCounter initiated to 0, but var is not set to 0.
So in order to reuse var I need to set all its values to 0.
There are several ways to do that.
I could use the Initiate method on var.
However, as you can see, The initiate method takes me more lines of code then the ctr of SuperCounter, but both do the same job eventually.
For the sake of this example lets say I cannot call explictly the ctr.
So I would want a similar method to the ctr of SuperCounter instead of the Initaite method.

The partial solution I have found to this problem, is simply having a static initiated instance.
Lets say in addition to var I also have:
SuperCounter Initiator;

So in order to set zeros to var, I could simply do:
var = Initiator.
And then I wouldnt need the Initiate method.
But then it means all of my operator = methods must have a certain purpose, and I won't be able to use them for another purpose I might wanted them to have.

Does this make it more clear?

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
Quote:
Original post by The C modest god
Why did you use Un? Is your reply not proper now?


well, my typo shows how much I actually cared to reply to you... I didn't even proof-read my own response even though I advised you to check your own spelling and grammar, however are you able to tell the difference?

I was replying to YOU, someone who obviously intended to get in touch with WG21 in order to suggest language "enhancements" while apparently not even being able to phrase comprehensible, correct sentences.

Unlike the mistakes you have made, the mistake that I made and that you pointed out, is in fact mainly a TYPO, that is the u/i keys are pretty damn close on the majority of standard keyboards. Typos can usually be forgiven, I mean it's in the nature of the thing if you type at > 300WPM.

And then again: my original advice wasn't meant as an attach, rather it was truly sincere advice for the case that you should actually consider getting in touch with WG21, in fact you normally wouldn't even be taken seriously on most newsgroups if you were to post using the style that you did use.

Also, you may not realize it but you are asking many BASIC questions which indicates a lack of understanding for C++ in general, this is one thing you might really want to get sorted, as it would add credibility to your posts and suggestions, if you actually knew what you are talking about.

Finally, you might want to read up on the latest proposals for C++0x, to make sure that there aren't any other proposals conflicting/((((duplicating)))) w/ the one that you intend to make...



I will give you an example:

*** Source Snippet Removed ***
var will be constructed and all the ints inside it will be set to 0.
I have used var somehow and changed the values of num within it, to values different from 0.
Now I need to use another SuperCounter.
I don't need to use var anymore, so I could reuse var instead of having another variable in the stack or using heap allocated instance of SuperCounter.
I need this SuperCounter initiated to 0, but var is not set to 0.
So in order to reuse var I need to set all its values to 0.
There are several ways to do that.
I could use the Initiate method on var.
However, as you can see, The initiate method takes me more lines of code then the ctr of SuperCounter, but both do the same job eventually.
For the sake of this example lets say I cannot call explictly the ctr.
So I would want a similar method to the ctr of SuperCounter instead of the Initaite method.

The partial solution I have found to this problem, is simply having a static initiated instance.
Lets say in addition to var I also have:
SuperCounter Initiator;

So in order to set zeros to var, I could simply do:
var = Initiator.
And then I wouldnt need the Initiate method.
But then it means all of my operator = methods must have a certain purpose, and I won't be able to use them for another purpose I might wanted them to have.

Does this makes it more clear?[/quote]

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
Quote:

Does this make it more clear?
It's a crystal clear example of why one should learn to walk before one tries to run.

Your 'problem' has several excellent solutions which fit into C++, starting with the creation of a general Resettable class.

Or with the more appropriate solution of not muddying your programs' semantics by using the same object to represent two distinct conceptual entities (different counters). This'll bite you if your code depends on counter identity for checking something...

Share this post


Link to post
Share on other sites
Personally I don't feel this should be a feature added to C++, I think the way you did it in your example is fine, at least you can see what's going you when you read it.

The other thing I'd say is that in you're example I'd ague that inheritence would be a better way to go but I do understand it's just an example to highlight your point.

Share this post


Link to post
Share on other sites
Quote:
Original post by The C modest god
I don't need to use var anymore, so I could reuse var instead of having another variable in the stack or using heap allocated instance of SuperCounter.

Allocating memory on the stack is pretty much free, the only problem is if the constructor is complicated and it's in this case. You shouldn't re-use the variable you should create a new instance, don't optimize prematurely.

Quote:
However, as you can see, The initiate method takes me more lines of code then the ctr of SuperCounter, but both do the same job eventually.

Why do you care about an extra line of code? The performance will be the same.

Quote:
For the sake of this example lets say I cannot call explictly the ctr.

Why? You want to improve a subset of C++ with one of the things in C++?

Quote:
So I would want a similar method to the ctr of SuperCounter instead of the Initaite method.

Why would you want that?

Quote:
The partial solution I have found to this problem, is simply having a static initiated instance.
Lets say in addition to var I also have:
SuperCounter Initiator;

So in order to set zeros to var, I could simply do:
var = Initiator.
And then I wouldnt need the Initiate method.
But then it means all of my operator = methods must have a certain purpose, and I won't be able to use them for another purpose I might wanted them to have.

This method would take even more lines of code. Also operator= should have exactly one purpose and that is to assign the left hand side to the right hand side, if you assign a super counter to an empty super counter, then the super counter should be empty.

Quote:
Does this make it more clear?

It makes it clear what you intend to do, but not why.

If one actually had a good reason to make such a feature, then it could easily be added with some template classes, of course you wouldn't have all the syntactic sugar.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
BTW, we've had a discussion for C++0x proposals here at GameDev.net, too!

Share this post


Link to post
Share on other sites
Quote:

...
Now I need to use another SuperCounter


Yes - you need another one. Not the same one - a different one.

If that's all you need, then just create a new object on the stack.

If you're asking for a way to create an object in the same memory as one that already exists:


SuperCounter var;
var.~SuperCounter();
new(&var) SuperCounter();





You aren't going to gain any efficiency for stack allocation though.

Share this post


Link to post
Share on other sites
Ok, I have showed you what is this feature.
Now I will try to give you an example of why.
This example is a very simplified and conceptual version of what I want to do.



template <class T>
ReferencePointer {
public:
~ReferencePointer() {this->ptr = NULL; (*this->pInstances)--;};
T * ptr;
int * pInstances;
void SetMember (MemberClass<T> & Source)
{
this->ptr = &Source.data;
this->pInstances = &Source.Instances;
Source.Instances++;
}
};

template <class T>
MemberClass {
template <class T>
friend class RefernecePointer;
public:
MemberClass () { this->Instances = 0; };
~MemberClass () { if (this->Instances!=0) {/*Do error*/};};
T data;
int Instances;

};

class B {
public:
ReferencePointer<B> BPtr;
};

class A {
public:
MemberClass<B> a1;
MemberClass<B> a2;
};

A * foo;

foo = new A ();
foo->a1.BPtr.SetMember (foo->a2);
foo->a2.BPtr.SetMember (foo->a1);

delete foo; // <= will generate error due to cyclic reference








Edit: So I would want a method that I will operate on class A instance, and it will recurcivly call the same methods on MemberClass\<B\> which will call the same method on ReferencePointer\<b\>, which will release its reference to the member class.

Share this post


Link to post
Share on other sites
That doesn't really help any. What are you actually proposing, and what are you trying to accomplish? Here's what I make of your (very poorly phrased) descriptions:

You are proposing the addition of a function called "recur" that would be a standard property of an object, like a constructor or destructor is. This function, when invoked on an object A, would be executed and then the "recur" method of every sub-object within A would be invoked. Now, I'll assume that the recursive invocation on sub-objects is handled implicitly by the compiler, or else there is zero point to making this functionality standard. So, an example might be:


#include <iostream>

struct A
{
void recur(void) { std::cout << "A::recur " }
};

struct B
{
void recur(void) { std::cout << "B::recur " }

A myA1;
A myA2;
};

// in main:
B foo;
foo.recur();


would print "B::recur A::recur A::recur" correct?

While interesting as a toy, this is not a useful enough idiom to merit addition to the language. recur() could not be meaningully overloaded in any way -- it must take no parameters and return nothing, otherwise the compiler could not do the implicit recursion, which, as I said before, is the only reason this might ever be useful -- and that limits what it could be used for. Also, how would recur() work for pointers or references? It would be possible for recur() to loop infinitely, which makes it dangerous to call in a generic manner (e.g., on a template parameter type).

There's no reason you can't implement this behavior specifically for the situation where you (think) you need it. It will be better that way. I'm also not convinced it helps you solve your "problem" (which appears to revolve around using your terrible hand-rolled smart pointer incorrectly to generate cyclical dependancies; this is what "weak pointers" are for).

There are other issues; I will perhaps comment again when I have more time. In the meantime, why don't you try to explain yourself a little better so that I, and others, can work on more than assumptions.

Share this post


Link to post
Share on other sites
Quote:
Original post by The C modest god
Ok, I have showed you what is this feature.
Now I will try to give you an example of why.
This example is a very simplified and conceptual version of what I want to do.

*** Source Snippet Removed ***

Edit: So I would want a method that I will operate on class A instance, and it will recurcivly call the same methods on MemberClass\<B\> which will call the same method on ReferencePointer\<b\>, which will release its reference to the member class.


No offense intended, but why do you want to modify the language itself when your whole problem comes from a badly designed solution? Two objects who own each other will not work, was never supposed to work, and will probably never work.

Regards,

Share this post


Link to post
Share on other sites
Quote:
Original post by Emmanuel Deloget
Quote:
Original post by The C modest god
Ok, I have showed you what is this feature.
Now I will try to give you an example of why.
This example is a very simplified and conceptual version of what I want to do.

*** Source Snippet Removed ***

Edit: So I would want a method that I will operate on class A instance, and it will recurcivly call the same methods on MemberClass\<B\> which will call the same method on ReferencePointer\<b\>, which will release its reference to the member class.


No offense intended, but why do you want to modify the language itself when your whole problem comes from a badly designed solution? Two objects who own each other will not work, was never supposed to work, and will probably never work.

Regards,


I usually don't have cyclic references in my program, but it is possible sometimes.
Didnt you ever use a graph with circles?
But the cyclic reference is not the point.
The important thing is that you cant delete or release the information in one iteration. Because you don't know if you will encounter a MemberClass first or the ReferencePointer that points to it first.

Share this post


Link to post
Share on other sites
Quote:
Original post by jpetrie
That doesn't really help any. What are you actually proposing, and what are you trying to accomplish? Here's what I make of your (very poorly phrased) descriptions:

You are proposing the addition of a function called "recur" that would be a standard property of an object, like a constructor or destructor is. This function, when invoked on an object A, would be executed and then the "recur" method of every sub-object within A would be invoked. Now, I'll assume that the recursive invocation on sub-objects is handled implicitly by the compiler, or else there is zero point to making this functionality standard. So, an example might be:


#include <iostream>

struct A
{
void recur(void) { std::cout << "A::recur " }
};

struct B
{
void recur(void) { std::cout << "B::recur " }

A myA1;
A myA2;
};

// in main:
B foo;
foo.recur();


would print "B::recur A::recur A::recur" correct?

While interesting as a toy, this is not a useful enough idiom to merit addition to the language. recur() could not be meaningully overloaded in any way -- it must take no parameters and return nothing, otherwise the compiler could not do the implicit recursion, which, as I said before, is the only reason this might ever be useful -- and that limits what it could be used for. Also, how would recur() work for pointers or references? It would be possible for recur() to loop infinitely, which makes it dangerous to call in a generic manner (e.g., on a template parameter type).

There is no problem of infinity loop.
Notice that ReferencePointer<T> contains T * Ptr and int * pInstances.
Both are pointers. Pointrs do not have sub classes, so it will not call the Recur of the object Ptr points to. Just like a dtr.
On the other hand, MemberClass<T> has T Data. So it will call the Recur of Data which will make the desirable effect.
Additionally, you cannot make a "data loop" with member class, such as:

class A {
public:
A Data;
};

So Recur wont be called recusrivly in an infinty loop.

Actually, Recur should be more like operator =, so in your example, the output will be just "B::recur"
If you change the code to:

#include <iostream>

struct A
{
void recur(void) { std::cout << "A::recur " }
};

struct B
{
A myA1;
A myA2;
};

// in main:
B foo;
foo.recur();



The output will be "A::recur A::recur"

[Edited by - The C modest god on September 28, 2006 3:07:26 PM]

Share this post


Link to post
Share on other sites
Quote:
Original post by The C modest god
What is the standard procedure to add such a feature?


The TR2 Call for Proposals suggests this

Quote:
To submit a proposal: post to comp.std.c++, ask a member of the standards committee to include it as a paper in a committee mailing, or email Howard Hinnant. You can submit a proposal in PDF, HTML, or plain text.

You should either plan to attend a standardization committee meeting yourself (see http://www.open-std.org/jtc1/sc22/wg21/docs/meetings for meeting schedules), or find a committee member who will present your proposal for you. Getting a proposal accepted is an interactive process, and it is almost certain that the committee will have questions. At the least, you need to be willing to respond to email queries.

The standardization committee is working on the second technical report on library extensions ("TR2") at the same time as it is working on the new version of the standard ("C++0x"). The two schedules are decoupled, but it is currently expected that TR2 will be published after C++0x.

Most proposals should be targeted for TR2, not for C++0x. A C++0x library proposal will be judged by much stricter standards than a TR2 proposal. A C++0x proposal will be accepted only if it can be shown to be very low risk and only if the committee is certain that it can be finalized without jeopardizing the schedule for C++0x. Experimental proposals will not be considered for C++0x. For TR2, however, the committee will be less conservative.

Proposals for C++0x library extensions must be received by October 1, 2005. Proposals for TR2 library extensions must be received by October 1, 2006.


Though you should be aware that members of the standards committee are busy people and will be rather unhappy if you submit anything that they consider to be a waste of their time. [wink]

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this