Sign in to follow this  
nlbs

invoking Base::virtualMethod instead of Derived

Recommended Posts

In my class Js::Object I've an operator() overload which returns Js::JType* all Other Classes in Js Namespace e.g. Js::Number, Js::String etc.. even Js::Object inherits from Js::JType
Js::JType* &operator()(const string& key);
source
/**
typedef std::map<string, Js::JType*> ElemMap;
*/
Js::JType* &Js::Object::operator()(const string& key){
	ElemMap::iterator it=list.find(key);
	if(it != list.end()){
		return (Js::JType* &)(it->second);
	}else{
		Js::JType* x = new Js::JType;
		list.insert(make_pair(key, x));
		return x;
	}
}

and this is how I am using it.
Js::Object o;
o("math") = new Js::String("Hello World");
Now If everything is ok.
o("math")->commit()
should return "Hello World" (with quotes as std::string) then it will invoke Js::String::commit() But Its invoking Js::JType::commit() and thus its returning null (as std::string) e.g. in other words its invoking the commit() of grand parent Class not of the intended class. and yes commit is virtual. Hope I am able to clarify the problem.

Share this post


Link to post
Share on other sites
The problem is, when you get an iterator into a std::map, the values held are copied. So your op() returns a reference to a local copy of the pointer, not a reference to the pointer stored in the map itself.

I don't think there's any sensible way to make it work the way you intended. But you could have your op() return just the pointer that would then be used for access to the pointed-to object, and provide another function for inserting values into the map.

Share this post


Link to post
Share on other sites
As Oxyd said, "return x" is returning the address of a local variable, and as soon as x leaves scope that address no longer exists. You should be returning list.insert(make_pair(key, x)).first.second, which is the address of the newly inserted value.

Share this post


Link to post
Share on other sites
You have a memory leak. You are returning a reference to a pointer allocated with "new", and then overwriting it with another pointer allocated with "new", without a "delete" call.

It is semantically incorrect. The "else" part does not return a reference to a pointer in the map, it returns a reference to a local variable. I think this is the cause of your error.

I believe your code could be expressed shorter:

Js::JType* &Js::Object::operator()(const string& key){
ElemMap::iterator it=list.find(key);
if(it != list.end()){
// (Js::JType* &) is unnecessary
return it->second;
}else{
JS::JType *ptr = 0;
list.insert(make_pair(key, ptr));
return list[key];
}

}


This code doesn't leak - but it could potentially return NULL when the key isn't found. The calling code would have to be able to handle this.

An alternative would be to use smart pointers.

In fact, I believe the code code potentially be shortened to:

Js::JType* &Js::Object::operator()(const string& key)
{
return list[key];

}


The only issue is if a default constructed pointer (as opposed to an uninitialised pointer) is *guarenteed* to be 0. I think it might be, but I never store raw pointers in containers so I've never looked into it.

Share this post


Link to post
Share on other sites
I have questioned the sanity of such approach before. But if well defined, and carefully coded, it can work.

Personally, I once used such approach, but I used templates to specify return types, resulting in compile-time checks to avoid many problems.

To use fully run-time evaluated system, this is how I would approach it (using a proxy holder for return types).
#include <iostream>
#include <string>
#include <map>

struct JType {
JType() { std::cout << "JType()" << std::endl; }
virtual ~JType() { std::cout << "~JType()" << std::endl; }
virtual void commit() = 0;
};

struct JDefault : public JType {
JDefault() { std::cout << "JDefault()" << std::endl; }
~JDefault() { std::cout << "~JDefault()" << std::endl; }
void commit() { std::cout << "Commit not supported" << std::endl; }
};

struct JString : public JType {
JString() { std::cout << "JString()" << std::endl; }
~JString() { std::cout << "~JString()" << std::endl; }
void commit() { std::cout << "Hello World" << std::endl; }
};

class Object {
typedef JType * T;
typedef std::map<std::string, T> List;

// non-copyable, too messy to implement
Object(const Object &) {}
Object operator=(const Object &) {}

struct Proxy {
friend class Object;

Proxy & operator=(T rhs) {
clear();
ref = rhs;
return *this;
}

bool exists() const { return ref != NULL; }
void clear() const { delete ref; ref = NULL; }
T operator->() const { return value(); }
T operator*() const { return value(); }
private:
Proxy(const List::iterator & i) : ref(i->second) {}
Proxy(const Proxy & other) : ref(other.ref) {}

T value() const {
static JDefault def;
return (ref == NULL) ? &def : ref;
}

// assignment can't be implemented
Proxy & operator=(const Proxy &) { }
T & ref;
};

List list;
public:
Object() {}
~Object() {
List::iterator i = list.begin();
for (List::iterator i = list.begin(); i!= list.end(); ++i) delete i->second;
}

Proxy operator[](const std::string & key) {
List::iterator i = list.find(key);
if (i != list.end()) {
return Proxy(i);
} else {
return Proxy(list.insert(list.end(), std::make_pair(key, T(NULL))));
}
}
bool has(const std::string & key) {
return list.count(key) != 0;
}
};

int main(int argc, char* argv[])
{
Object o;
o["math"] = new JString();
if (o["empty"].exists()) std::cout << "'empty' should not exist" << std::endl;
o["math"]->commit();
o["math"].clear();
o["math"]->commit();
o["empty"]->commit();
}


I have tried to think of all the corner cases while limiting the code to nothing and absolutely nothing beyond the given problem. Even with that I'm not sure I got it right (C++ is annoying in that way).

In above case Proxy is temporary holder for reference to actual pointer which resides inside std::map's node. Proxy should be transient object that cannot persist beyond scope of caller. It also relies on map not being changed while its alive.

In release builds, Proxy is completely eliminated, all operations on it result in query of actual holder of pointer.

Lastly, there's the performance penalty to consider. Each time a variable is accessed, map must be searched. This could be solved by allowing Proxy to be cached, but that throws safety out of window.


Finally: std::map is designed the way it is for a good reason. Unlike managed objects, where NULL/null is a given, map[] may result in undefined behavior. It is almost without exception better to use the map properly rather than trying to go against the design of C++.

Also - Python, PHP, Lua or similar would be much better choice to implement system like this. C++ is simply the wrong language for this.

Share this post


Link to post
Share on other sites
Ya this way I think would be good.
The mechanism you have used is stl containers way.
I thought this mechanism and named it JAdapter (cause I want both JArray and JObject would share it) anyway as you brought the Friendly Proxy mechanism lets talk about that.
But 1 question.


JNumber x = "Hello World";
Object o;
o["x"] = x;
o["x"] = new JString("y");
//Here x will be used in some other purpouse too.
std::cout<<x.toStdString()<<std::endl;



Now upon reassignment clear() is being called can x be called after o["x"] has been reassigned as you are doing delete ref on clear()??

If you delete that then it cant be used in other purpouse latter after reassignment.

and if you don't delete it would cause memory leak.

So what can be done in this situation !!

Share this post


Link to post
Share on other sites
Quote:
Original post by nlbs
Now upon reassignment clear() is being called can x be called after o["x"] has been reassigned as you are doing delete ref on clear()??

If you delete that then it cant be used in other purpouse latter after reassignment.

and if you don't delete it would cause memory leak.

So what can be done in this situation !!


Nothing, since it wouldn't even compile.

What you meant was:
	JString js;
o["a"] = &js;

I don't care about this case, since you deliberately ignore it in your design. If you require user to allocate the objects, and container must release them, that's generally fragile design.

I've said it before, the best way is to not do things this way, or look at competing approaches, such as boost::any.

But most importantly, C++ is really poor language to implement such features. It can be done, but full implementation involves a lot of magic template fu and various dynamic tests. These techniques have been explored several times, but they remain mostly obscure oddities with little practical use.

In current implementation objects managed by container must derive from JType and be allocated with new. Working around that would require JType to properly implement cloning and more. There really is a good reason why map works the way it works.

If anything, you might want to try:
template < class U >
Proxy & operator=(const U & rhs) {
clear();
ref = new U(rhs);
return *this;
}
That allows you to manage polymorphic behavior inside the container, and let compiler take care of type safety. This would be safe to use with auto-allocated objects as well, while retaining polymorphic behavior. It does cause problems when assigning base class. You could provide a virtual clone() method or something.
	Object o;
JString js;
o["a"] = js;
o["math"] = JString();

Share this post


Link to post
Share on other sites
In your Proxy class why are you doing T & ref;
why not just T . cause JType* would store a pointer but I cant understand why a reference to a pointer is required.

and secondly I cant understand why Object Class is non-copyable

Share this post


Link to post
Share on other sites
Quote:
Original post by nlbs
In your Proxy class why are you doing T & ref;
why not just T . cause JType* would store a pointer but I cant understand why a reference to a pointer is required.


Because you need to modify the pointer, not the contents of pointer. Simple example.
typedef JType * JTypePtr;

void assign(JTypePtr & ptr, const JTypePtr & newValue) {
delete ptr;
ptr = newValue;
};

...

std::pair<std::string, JType *> entry.
assign(entry, new JString());
It would be possible to use C style syntax, and store JType ** instead. But given the nature of the problem, that is not necessary.

Quote:
and secondly I cant understand why Object Class is non-copyable


Because map contains raw pointers that it needs to clean up. Whenever you copy Object, you need to copy the contents of map. This is impossible due to polymorphic nature of JType *. To make map copyable, you first need to provide JType with virtual constructor, then implement copy constructor and assignment operator correctly for Object.

Share this post


Link to post
Share on other sites
So you meant I need to do something like.

Object(const Object & r) {
this = r.clone();
}
Object operator=(const Object & r){
this = r.clone();
}


Right ??

If I code like this e.g. `this =` syntax says `lvalue required as left operand of assignment`

I meant I cant understand how to call/use the clone() from copy constructor or operator=()

Share this post


Link to post
Share on other sites
Quote:
Original post by nlbs
So you meant I need to do something like.
*** Source Snippet Removed ***
Right ??

If I code like this e.g. `this =` syntax says `lvalue required as left operand of assignment`

I meant I cant understand how to call/use the clone() from copy constructor or operator=()


You need to add it to JType. Something like this:
#include <iostream>
#include <string>
#include <map>

struct JType {
JType() { std::cout << "JType()" << std::endl; }
virtual ~JType() { std::cout << "~JType()" << std::endl; }
virtual void commit() = 0;
virtual JType * clone() const = 0;
};

struct JDefault : public JType {
JDefault() { std::cout << "JDefault()" << std::endl; }
~JDefault() { std::cout << "~JDefault()" << std::endl; }
void commit() { std::cout << "Commit not supported" << std::endl; }
JDefault * clone() const { return new JDefault(*this); }
};

struct JString : public JType {
JString(const std::string & value = "Hello World")
: s(value)
{
std::cout << "JString()" << std::endl;
}
~JString() { std::cout << "~JString()" << std::endl; }
void commit() { std::cout << s << std::endl; }
JString * clone() const { return new JString(*this); }
private:
std::string s;
};

class Object {
typedef JType * T;
typedef std::map<std::string, T> List;

struct Proxy {
friend class Object;

template < class U >
Proxy & operator=(const U & rhs) {
clear();
ref = new U(rhs);
return *this;
}

bool exists() const { return ref != NULL; }
void clear() { delete ref; ref = NULL; }
T operator->() const { return value(); }
T operator*() const { return value(); }
private:
Proxy(const List::iterator & i) : ref(i->second) {}
Proxy(const Proxy & other) : ref(other.ref) {}
// assignment isn't allowed
Proxy & operator=(const Proxy &) { }

T value() const {
static JDefault def;
return (ref == NULL) ? &def : ref;
}

T & ref;
};

struct ManagedMap {
~ManagedMap() {
List::iterator i = list.begin();
for (List::iterator i = list.begin(); i!= list.end(); ++i) delete i->second;
}
List::iterator insert(const std::string & key) {
return list.insert(list.end(), std::make_pair(key, T(NULL)));
}
List list;
};

void swap(ManagedMap & lhs, ManagedMap & rhs) {
std::swap(lhs.list, rhs.list);
}

List & list() { return entries.list; }
const List & list() const { return entries.list; }

ManagedMap entries;
public:
Object() {}

Object(const Object & other) {
ManagedMap temp;
for (List::const_iterator i = other.list().begin(); i != other.list().end(); ++i) {
List::iterator curr = temp.insert(i->first);
if (i->second != NULL) curr->second = i->second->clone();
}
swap(entries, temp);
}

Object & operator=(const Object & other) {
Object o(other);
swap(entries, o.entries);
return *this;
}

~Object() {}

Proxy operator[](const std::string & key) {
List::iterator i = list().find(key);
if (i != list().end()) {
return Proxy(i);
} else {
return Proxy(entries.insert(key));
}
}
bool has(const std::string & key) const {
return list().count(key) != 0;
}
};

int main(int argc, char* argv[])
{
Object o;
JString js;
o["a"] = js;
o["math"] = JString();
Object q;
o = o;
q = o;
Object r;
r = q;
r["foo"] = JDefault();
r["bar"] = JString("bar");
o = r;
if (o["empty"].exists()) std::cout << "'empty' should not exist" << std::endl;
o["math"]->commit();
o["math"].clear();
o["math"]->commit();
o["foo"]->commit();
o["bar"]->commit();
o["empty"]->commit();
}


A few comments on that:
- I still don't guarantee I covered all the corner cases
- This is why C++ is hard
- To understand why things are implemented in this way, best references are Exceptional C++, More Exceptional C++ and few others.

I'd strongly suggest you look into those sources and examine the finer points of C++ before trying designs like this. The difference between something that compiles and something that works somewhat reliably is simply too big in C++.

Share this post


Link to post
Share on other sites
would you mind to clarify why you used ManagedMap instead of using simply std::map
why did you use swap instead of copy ??

[Edited by - nlbs on November 10, 2008 1:18:55 AM]

Share this post


Link to post
Share on other sites
Quote:
Original post by nlbs
would you mind to clarify why you used ManagedMap instead of using simply std::map
why did you use swap instead of copy ??


To properly implement memory management and attempt to provide exception safety in cases where Object gets copied.

That is covered in the books I mentioned, as well as various other sources, but it's somewhat extensive topic that I cannot summarize in a few sentences.

Share this post


Link to post
Share on other sites
But the thing is.

Object o;
o["x"] = JString("X");
Object p;
p["y"] = JString("Y");
//Now when you do
o = p;


Now p should be copied into o and o should also contain what p contains.
But as you are using swap the contents of p is going to o and contents of o is going to p and obviously its not intented by the term COPY.

This is what I meant to say.

Share this post


Link to post
Share on other sites
Quote:
Original post by nlbs
Now p should be copied into o and o should also contain what p contains.


Maybe that is what you require, but it is definitely not implied by syntax. If you need such operation, then define a merge() function or something - but never assignment operator.

Quote:
But as you are using swap the contents of p is going to o and contents of o is going to p and obviously its not intented by the term COPY.


Object o;
o["x"] = JString("X"); // o contains x
Object p;
p["y"] = JString("Y"); // p contains y
//Now when you do
o = p; // o contains y
// p contains y, x no longer exist


This is exactly what assignment operator does.

Object & operator=(const Object & other) {
Object o(other); // make a copy
swap(entries, o.entries); // swap with copy
return *this; // destroy copy
}

other is not modified.

Share this post


Link to post
Share on other sites
Thanks for clearing the fact.
Quote:
Original post by Antheus
Quote:
Original post by nlbs
Now p should be copied into o and o should also contain what p contains.


Maybe that is what you require, but it is definitely not implied by syntax. If you need such operation, then define a merge() function or something - but never assignment operator.


No thats definitely not what I want to do. first I thought that this is what your code does. However you have clarified that just now.

Now another question is. we are not storing raw pointers in Object Class we are storing a std::map container instance which is storing raw pointers.

so why there would be a need to use another ManagedMap..

I meant to say what are the difficulties we would fetch if we use std::map only no ManagedMap.

Thanks again.

Share this post


Link to post
Share on other sites
Quote:
Original post by nlbs

so why there would be a need to use another ManagedMap..

I meant to say what are the difficulties we would fetch if we use std::map only no ManagedMap.


It is needed to define custom destructor that will delete the raw pointers we stored in there. std::map only releases what it allocates.

And since we auto-allocate ManagedMap instances, the compiler makes sure whenever map is deallocated, so are all instances we allocated with new.

It isn't strictly required, but is considerably more elegant. Without that, we'd need to use try/catch block to handle problems that occur during copy construction or assignment.

Share this post


Link to post
Share on other sites
I found a risk but I dont know how much important it is.
suppose I've a JString* member variable.
and somebody have inserted it into a Local Object Instance which gets auto destructed. (I have no reason to believe that people who uses my class are smart enough)

Now the member variable of JString* Type will also get destructed.

But it was not intended.

should I use a std::map of std::auto_ptr in managed map
and JType -> auto_ptr<JType> abstractions will be provided by ManagedMap itself ?? also I dont need to do explicit delete operation on pointers as I am storing auto_ptr Instances on the map.

would this solve the above mentioned problem ??
would any other problem / risk / corner case would appear ??

Share this post


Link to post
Share on other sites
Quote:
Original post by nlbs
I found a risk but I dont know how much important it is.
suppose I've a JString* member variable.
and somebody have inserted it into a Local Object Instance which gets auto destructed. (I have no reason to believe that people who uses my class are smart enough)


Can you show an example?

Quote:
should I use a std::map of std::auto_ptr in managed map


auto_ptr cannot be used with standard library containers.

Share this post


Link to post
Share on other sites
Quote:
Original post by Antheus
Quote:
Original post by nlbs
I found a risk but I dont know how much important it is.
suppose I've a JString* member variable.
and somebody have inserted it into a Local Object Instance which gets auto destructed. (I have no reason to believe that people who uses my class are smart enough)


Can you show an example?



class MyApplication: public Application{
private:
JString* pilot;
public:
void sub(){
Object o;
o["x"] = JString("X");
o["p"] = *pilot;
o["s"] = *(this->root);
//assume root is another JType Derived Object which is comming from base Class
}
}




Now when sub will end both pilot and root will be destructed.
Which is not intended.

EDIT{
also I cant make an Proxy::operator=(Proxy*) overload on Proxy if delete is preset cause &StackObject can also be passed in that way which can not be deleted using delete operator
}

Again I'll requote
Quote:
Original post by nlbs(I have no reason to believe that people who uses my class are smart enough)


Quote:
Original post by Antheus
Quote:
should I use a std::map of std::auto_ptr in managed map


auto_ptr cannot be used with standard library containers.


Why ??

[Edited by - nlbs on November 11, 2008 11:07:10 AM]

Share this post


Link to post
Share on other sites
Quote:
Original post by nlbs

*** Source Snippet Removed ***

Now when sub will end both pilot and root will be destructed.
Which is not intended.


The above works properly, since assignments perform a copy of value, not pointer. You cannot assign a pointer, nor does Object modify the rhs.

Quote:
also I cant make an Proxy::operator=(Proxy*) overload on Proxy if delete is preset cause &StackObject can also be passed in that way which can not be deleted using delete operator


Yes, Proxy(const Proxy &) is private. It cannot be implemented without being converted into a proper iterator-like concept with reference to Object.

The reason for Proxy being uncopyable is deliberate in order to avoid:
template < class T >
void snafu(T t) {
T local(t);
T another(local);
}

snafu(o["x"]) // we just copied our proxy, even though it's private


Quote:
Again I'll requote
Quote:
Original post by nlbs(I have no reason to believe that people who uses my class are smart enough)
The implementation I provided should be fool proof from design aspect. I didn't verify it enough though, and there's at least one potential pitfall in it.

For example, the following would be better way to handle assignment:
template < class U >
Proxy & operator=(const U & rhs) {
std::auto_ptr<T> ptr(nrhs.clone();
delete ref;
ref = ptr->release();
return *this;
}
The rest should behave properly though.

There is however no reasonable way to protect against passing invalid instances in C++.

Uses such as 'o["p"] = *pilot;' are simply asking for trouble, but cannot be prevented.

Quote:
Why ??


auto_ptr<int> a(new foo);
auto_ptr<int>b(a->get())
a->get() // undefined behavior
auto_ptr takes exclusive ownership of contained pointer. Copying inside std::containers does not guarantee to be compliant with auto_ptr.

Share this post


Link to post
Share on other sites
Quote:
Original post by Antheus
Quote:
Original post by nlbs
*** Source Snippet Removed ***
Now when sub will end both pilot and root will be destructed.
Which is not intended.


The above works properly, since assignments perform a copy of value, not pointer. You cannot assign a pointer, nor does Object modify the rhs.

Sorry I overlooked the cloning facts.

Actually I want both

o["p"] = JString("Hello");
o["p"] = new JString("Hello");

be valid.

Now if somebody does o["p"] = &StackObject; Its his fault that after the scope is finished o["p"] is pointing to null pointer.

and at the same time I am handling a risk that o["p"] might not contain a pointer to Object that is created by new. so delete operation cannot be done on that.

So I cant do delete in destructor if I allow assigning Pointers.
But sadly I want to allow Both (for Syntactic Flexibility).

I would not like a scoped Pointer or a reference counted garbage collecter or any such mechanism here cause Here I am coding a Container.
and The Elements that the user is inserting into that container shouldn't be deleted without explicit operation by user.
However the new Elements That my container is creating dynamically should be deleted by my container itself as the user might be compleately unaware about those.

So I have thought out an way.

When User is doing


o["p"] = JString("Hello");//The new Object created is owned By o Object itself
o["p"] = new JString("Hello");
o["p"] = &StackObject;
//In the last two Object its not owned By o Object itself.


I think The Object SHOULD delete only those that are owned by it.

So I'll Just keep an track to all new allocated Objects (on a vector<JType*>) which are created from const JType& Type
and do delete operation on them in JObject's destructor.

Now How much effecient this way is ??

Share this post


Link to post
Share on other sites
Quote:
Original post by nlbs
When User is doing


o["p"] = JString("Hello");//The new Object created is owned By o Object itself
o["p"] = new JString("Hello");
o["p"] = &StackObject;
//In the last two Object its not owned By o Object itself.


I think The Object SHOULD delete only those that are owned by it.

So I'll Just keep an track to all new allocated Objects (on a vector<JType*>) which are created from const JType& Type
and do delete operation on them in JObject's destructor.


void fubar(Object & o) {
JString s("s");
o["s"] = &s;
};

Object o;
fubar(o);
std::cout << o["s"];
At this point, you're in land of undefined behavior.

o["p"] = new JString("Hello");
This is memory leak. Container will not release it.

And then:
Object o;
JString * js = new JString();
o["js"] = js;
Object q = o;
delete js;
std::cout << q["js"];
Does q need to clean-up js? Does it make a copy? When you delete an instance, how do you know it's not part of any container?

Quote:
Now How much effecient this way is ??


At this point all I can say is I tried to present all the issues that are involved when dealing with raw pointers, had to double-check the code several times to *try* to do the right thing and provide a safe approach for the user. The approach I presented is optimal with regard to memory use and data integrity. It's the sole purpose for it - smart pointers can be used instead, but you might encounter issues with polymorphic behavior.

The only thing I have left beyond the books I already recommended is this, which I feel you should study in entirety to understand every single concept related to memory management, starting with auto vs. heap allocated objects, as well as type-casting pitfalls, reference and pointer semantics and other crucial issues.

Only by understanding every single subtle detail of that will you be able to design a system that is robust enough for your users, yet still meets all the requirements.

I personally would suggest your switch to Python.

Share this post


Link to post
Share on other sites
Quote:
Original post by Antheus
void fubar(Object & o) {
JString s("s");
o["s"] = &s
};

Object o;
fubar(o);
std::cout << o["s"];
At this point, you're in land of undefined behavior.


Firstly it will not show undefined behavior cause I am constructing a new Object from its clone. whenever some reference is specified.
and that clone (if created by JObject itself is destructed on its destructor).
So it will print s.
Quote:
Original post by Antheus
o["p"] = new JString("Hello");
This is memory leak. Container will not release it.

I believe it is C++ not Java so if the user really need automatic garbage collection he/she switch to Java or C# . In C++ whenever somebody uses/writes a New he should delete for that new. here this new is not coded by mine so its not my headech to delete it (or even if I delete it will/may confuse the user). and obviously if My Class JObject has written some new it would/should be deleted by JObject itself.So I dont need to think about this memory leak.


std::vector<std::string*> o;
o.push_back(new std::string("Hello World"));
//would std::vector delete this new string ??


Quote:
Original post by Antheus
And then:
Object o;
JString * js = new JString();
o["js"] = js;
Object q = o;
delete js;
std::cout << q["js"];
Does q need to clean-up js? Does it make a copy? When you delete an instance, how do you know it's not part of any container?


map<string, string*> o;
string* js = new string("js");
string* x = new string("x");
o["js"] = js;
o["x"] = x;
map<string, string*> q = o;
delete js;
cout<<*q["x"]<<endl;
cout<<*q["js"]<<endl;
This programm also exhibits the same behavior as you have just told ??
should q need to clean-up js ?? and obviously it causes Segfault.
But is it the fault of std::map user or teh std::map author ??

However in my code there is a way to detect a null(0x0) pointer and return a JUndefined Object.
Quote:
Original post by AntheusI personally would suggest your switch to Python.
I used to be a PHP coder since PHP3 to PHP5 now PHP6 is comming. I've made a framework on PHP and I want to bring teh same functionality C++ too I know Its not possible to achive 100% of my goal rather its somewhat absurd. however I can atleast achive 95% (rest due to Syntactic Complexity and Compiler based nature of C++).

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