• Advertisement
Sign in to follow this  

Why non-pod value types must have a destructor?

This topic is 440 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I have a very simple value type, looks like:

clase iterator
{
    char* m_p;

public:
    ptr_iterator()
        {}

    ptr_iterator(IN const ptr_iterator& rhs)
        : m_p(rhs.m_p)
        {}

    ptr_iterator& operator=(IN const ptr_iterator& rhs)
    {
        m_p = rhs.m_p;
        return (*this);
    }

    // ...
    char& operator*()
    {
        return (*m_p);
    }

    // ...
}

?

As you can see, it's a very simple iterator type for string. There is definitely no destructor  on it, whether explicitly created by me or implicitly created by the compiler.

 

Then when I register it to the engine:

   pENGINE->SetDefaultNamespace("stringEx");
   r = pENGINE->RegisterObjectType("iterator", sizeof(stringEx::iterator), asOBJ_VALUE|asOBJ_APP_CLASS_CAK); assert(r >= 0);
   r = pENGINE->RegisterObjectBehaviour("iterator", asBEHAVE_CONSTRUCT, "void f()", asFUNCTION(StrItConstruct), asCALL_CDECL_OBJLAST); assert(r >= 0);
   r = pENGINE->RegisterObjectBehaviour("iterator", asBEHAVE_CONSTRUCT, "void f(const stringEx::iterator &in)", asFUNCTION(StrItCopyConstruct), asCALL_CDECL_OBJLAST); assert(r >= 0);
   r = pENGINE->RegisterObjectMethod("iterator", "iterator& opAssign(const stringEx::iterator &in)", asFUNCTION(StrItAssign),  asCALL_CDECL_OBJLAST); assert(r >= 0);
   pENGINE->SetDefaultNamespace("");

?

I got an error:

[2017-02-02 00:56:08.675400 UTC+0800][Error]   (script_engine)
[MSG]  (0, 0):
@ Type 'iterator' is missing behaviours

[2017-02-02 00:56:08.676400 UTC+0800][Info]    (script_engine)
[MSG]  (0, 0):
@ A non-pod value type must have at least one constructor and the destructor behaviours

?

It confused me that why non-pod value types must have a destructor? Instead of "asOBJ_VALUE|asOBJ_APP_CLASS_CAK", should I use "asOBJ_VALUE|asOBJ_POD|asOBJ_APP_CLASS_CAK" to do the registration under this situation?

Edited by ASBai

Share this post


Link to post
Share on other sites
Advertisement

PS: It seems we can not register the de-reference unary operator ("*") ?

 

The iterator need it. We're using opCall instead, but it looks a bit odd:

// ...
	stringEx r;
	for (stringEx::iterator p=lhs.begin(); p!=lhs.end(); ++p)
	{
		r.push_back(p());
		p() = '!';
	}
// ...
Edited by ASBai

Share this post


Link to post
Share on other sites

From what you showed on your class implementation it is a POD class. POD means plain-old-data. POD classes doesn't require specific initialization routines, copy routines, or clean-up routines. It doesn't mean it cannot have specific initialization routines though.

 

A non-POD class on the other hand requires specific initialization routines to have a guaranteed initial state, e.g. to allocate dynamic memory, etc. In this case AngelScript also assumes a specific clean-up is needed just to be on the safe side.

 

You can use the flag asOBJ_POD in this case.

 

 

 

The de-reference unary operator ("*") doesn't exist in AngelScript, which is why you also cannot register the overload :)

Share this post


Link to post
Share on other sites

Ok, so I can specify my own constructor and assignment operator even for a POD class, right?

 

I hope "operator*" and "operator->" to be able to support in the future version :-)

Share this post


Link to post
Share on other sites

I've solved the iterator "operator->" problem by define two placeholder like:

struct PH1ST {};
struct PH2ND {};

// ...
const PH1ST i1ST;
const PH2ND i2ND;

// ...
r = pENGINE->RegisterObjectType("PH1ST", sizeof(PH1ST), asOBJ_VALUE|asOBJ_POD); assert(r >= 0);
r = pENGINE->RegisterObjectType("PH2ND", sizeof(PH2ND), asOBJ_VALUE|asOBJ_POD); assert(r >= 0);

r = pENGINE->RegisterGlobalProperty("const PH1ST first", (void*)&i1ST); assert(r >= 0);
r = pENGINE->RegisterGlobalProperty("const PH1ST key", (void*)&i1ST); assert(r >= 0);
r = pENGINE->RegisterGlobalProperty("const PH2ND second", (void*)&i2ND); assert(r >= 0);
r = pENGINE->RegisterGlobalProperty("const PH2ND value", (void*)&i2ND); assert(r >= 0);

?

And then define two overload operator() under the iterator class:

r = pENGINE->RegisterObjectMethod("iterator", "uint8& opCall(const PH1ST&in) const", asFUNCTION(StrItDeRef1st), asCALL_CDECL_OBJLAST); assert(r >= 0);
r = pENGINE->RegisterObjectMethod("iterator", "uint8& opCall(const PH2ND&in) const", asFUNCTION(StrItDeRef2nd), asCALL_CDECL_OBJLAST); assert(r >= 0);

// ...

?

Now we can do this in the script:

for (iterator p=container.begin(); p!=container.end(); ++p)
{
    // ...
    key = p(key) // or p(first) for "p->first"
    value = p(value) // or p(second) for "p->second"
}

?

Note that because the overload matching task is done in the compiling stage, so there is no run-time performance drops here. :cool:

Share this post


Link to post
Share on other sites

I'm still feeling strange for set both the "asOBJ_POD", "asOBJ_APP_CLASS", "asOBJ_APP_CLASS_CONSTRUCTOR", "asOBJ_APP_CLASS_ASSIGNMENT" and "asOBJ_APP_CLASS_COPY_CONSTRUCTOR" flags simultaneously.

 

Please confirm is this legal to set the flags as that?

Share this post


Link to post
Share on other sites

Yes, it is legal. These flags have completely different meanings and are not exclusive.

 

 

asOBJ_POD tells angelscript that the object can be treated as a POD, e.g. it is fine to do a bitwise copy of the object, it is not required to have a destructor, etc. 

 

The asOBJ_APP_XXX flags tell angelscript what the C++ object looks like, so angelscript can know how to properly pass objects of this type to registered functions using native calling conventions.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement