Unless I misunderstand things, it seems like a design flaw that both of these expressions are equally valid
SceneNode parent = this.getSceneNode();
SceneNode @parent = this.getSceneNode();
The first form improperly creates an instance of scene node, dereferences the pointer, and makes a copy of the object.
The second form is correct.
In my opinion, this is a design flaw for 4 reasons:
1. This syntax is rarely needed.
While technically I may want either of these, 95% of the time if someone calls a function that returns an object pointer, they use that pointer, rather than immediately dereference and copy the pointer.
2. Causes very difficult to find bugs.
For example, I have about 10 objects I deal with only through pointers, and never locally instantiate or copy. Doing so just does a shallow copy, and crashes in some weird place later. I can see myself and others constantly forgetting the @ and losing a lot of time debugging this.
3. Unintuitive
AngelScript is like C in every way except this. This mistake is practically begging to happen. I made it on my very first script, and it cost me 15 minutes to figure out why it was crashing in std::map, and then only because it was what I was immediately working on.
4. Used constantly
Every time I use the pointer, I need to remember @. I use it all over the place. Thus, I'm going to forget @ all over the place.
My only solution at this point is to purposely crash, so at least it crashes at the source of the problem, rather than somewhere unrelated later on.
void ScriptSceneNode::AddRef() {}
void ScriptSceneNode::ReleaseRef() {}
void ScriptSceneNodeConstructAssert(void *ptr)
{
ScriptManager::ScriptLog(std::string("Attempted to create instance of ScriptSceneNode! Use @ reference only."));
// Crash!
int *a=0;
*a=10;
}
...
ScriptManager::engine->RegisterObjectType("SceneNode", sizeof(Ogre::SceneNode), asOBJ_CLASS_CD);
ScriptManager::engine->RegisterObjectBehaviour("SceneNode", asBEHAVE_ADDREF, "void f()", asMETHOD(ScriptSceneNode, AddRef),asCALL_THISCALL);
ScriptManager::engine->RegisterObjectBehaviour("SceneNode", asBEHAVE_RELEASE, "void f()", asMETHOD(ScriptSceneNode, ReleaseRef),asCALL_THISCALL);
// You can't construct this class
ScriptManager::engine->RegisterObjectBehaviour("SceneNode", asBEHAVE_CONSTRUCT, "void f()", asFUNCTION(ScriptSceneNodeConstructAssert),asCALL_CDECL_OBJLAST);
ScriptManager::engine->RegisterObjectBehaviour("SceneNode", asBEHAVE_ASSIGNMENT, "SceneNode &f(const SceneNode &in)", asFUNCTION(ScriptSceneNodeConstructAssert),asCALL_CDECL_OBJLAST);