Jump to content
  • Advertisement
Sign in to follow this  

Problem with value type & opAssign

Recommended Posts


I try to wrap my head around operator behaviour, documentation does not say much for the C++ side, so I guess it should be probably simple but I can't get this to work:

# this works
vec3 a(1.0f);
vec3 b(0.0f);
vec3 c = a - b;

# this doesn't
Transform@ transform = Transform();
vec3 a(1.0f);
vec3 c = a - transform.position;

(70): No appropriate opAssign method found in 'vec3' for value assignment
(70): Previous error occurred while attempting to create a temporary copy of object

Transform register:

   asCHECK(engine->RegisterObjectType("Transform", 0, asOBJ_REF));
   asCHECK(engine->RegisterObjectBehaviour("Transform", asBEHAVE_FACTORY, "Transform@ f()", asMETHOD(SpatialWorld, makeTransform),
                                           asCALL_THISCALL_ASGLOBAL, this));
   asCHECK(engine->RegisterObjectBehaviour("Transform", asBEHAVE_ADDREF, "void f()", asMETHOD(TransformScriptProxy, addRef), asCALL_THISCALL));
   asCHECK(engine->RegisterObjectBehaviour("Transform", asBEHAVE_RELEASE, "void f()", asMETHOD(TransformScriptProxy, release), asCALL_THISCALL));

   asCHECK(engine->RegisterObjectMethod("Transform", "vec3 get_forward() const", asMETHOD(TransformScriptProxy, getForward), asCALL_THISCALL));
   asCHECK(engine->RegisterObjectMethod("Transform", "vec3 get_position() const", asMETHOD(TransformScriptProxy, getPosition), asCALL_THISCALL));
   asCHECK(engine->RegisterObjectMethod("Transform", "void set_position(const vec3 &in)", asMETHOD(TransformScriptProxy, setPosition), asCALL_THISCALL));

vec3 register:

 // Type & behaviours
   asCHECK(m_engine->RegisterObjectType("vec3", sizeof(glm::vec3), asOBJ_VALUE | asGetTypeTraits<glm::vec3>()));
   asCHECK(m_engine->RegisterObjectBehaviour("vec3", asBEHAVE_CONSTRUCT, "void f()", asFUNCTION(vec3_ConstructorEmpty), asCALL_CDECL_OBJLAST));

   asCHECK(m_engine->RegisterObjectBehaviour("vec3", asBEHAVE_CONSTRUCT, "void f(float, float, float)", asFUNCTION(vec3_Constructor), asCALL_CDECL_OBJFIRST));
   asCHECK(m_engine->RegisterObjectBehaviour("vec3", asBEHAVE_CONSTRUCT, "void f(float)", asFUNCTION(vec3_ConstructorScalar), asCALL_CDECL_OBJFIRST));
   asCHECK(m_engine->RegisterObjectBehaviour("vec3", asBEHAVE_DESTRUCT, "void f()", asFUNCTION(vec3_Destructor), asCALL_CDECL_OBJFIRST));

   // Properties
   asCHECK(m_engine->RegisterObjectProperty("vec3", "float x", asOFFSET(glm::vec3, x)));
   asCHECK(m_engine->RegisterObjectProperty("vec3", "float y", asOFFSET(glm::vec3, y)));
   asCHECK(m_engine->RegisterObjectProperty("vec3", "float z", asOFFSET(glm::vec3, z)));

   // Operators
   asCHECK(m_engine->RegisterObjectMethod("vec3", "vec3& opAddAssign(const vec3 &in) const", asMETHODPR(glm::vec3, operator+=, (const glm::vec3&), glm::vec3&), asCALL_THISCALL));
   asCHECK(m_engine->RegisterObjectMethod("vec3", "vec3& opMulAssign(const vec3 &in) const", asMETHODPR(glm::vec3, operator*=, (const glm::vec3&), glm::vec3&), asCALL_THISCALL));
   asCHECK(m_engine->RegisterObjectMethod("vec3", "vec3& opAssign(const vec3 &in) const", asMETHODPR(glm::vec3, operator=, (const glm::vec3&), glm::vec3&), asCALL_THISCALL));
   asCHECK(m_engine->RegisterObjectMethod("vec3", "vec3 opAdd(const vec3 &in) const", asFUNCTIONPR(glm::operator+, (const glm::vec3&, const glm::vec3&), glm::vec3), asCALL_CDECL_OBJLAST));
   asCHECK(m_engine->RegisterObjectMethod("vec3", "vec3 opSub(const vec3 &in) const", asFUNCTIONPR(glm::operator-, (const glm::vec3&, const glm::vec3&), glm::vec3), asCALL_CDECL_OBJLAST));
   asCHECK(m_engine->RegisterObjectMethod("vec3", "vec3 opMul(const vec3 &in) const", asFUNCTIONPR(glm::operator*, (const glm::vec3&, const glm::vec3&), glm::vec3), asCALL_CDECL_OBJLAST));
   asCHECK(m_engine->RegisterObjectMethod("vec3", "vec3 opMul_r(float) const", asFUNCTIONPR(glm::operator*, (float, const glm::vec3&), glm::vec3), asCALL_CDECL_OBJLAST));
   asCHECK(m_engine->RegisterObjectMethod("vec3", "vec3 opDiv(const vec3 &in) const", asFUNCTIONPR(glm::operator/, (const glm::vec3&, const glm::vec3&), glm::vec3), asCALL_CDECL_OBJLAST));
   // Methods
   asCHECK(m_engine->RegisterObjectMethod("vec3", "float length() const", asFUNCTIONPR(glm::length, (const glm::vec3&), float), asCALL_CDECL_OBJFIRST));
   asCHECK(m_engine->RegisterObjectMethod("vec3", "float dot(const vec3& in) const", asFUNCTIONPR(glm::dot, (const glm::vec3&, const glm::vec3&), float), asCALL_CDECL_OBJFIRST));
   asCHECK(m_engine->RegisterObjectMethod("vec3", "vec3 normalize() const", asFUNCTIONPR(glm::normalize, (const glm::vec3&), glm::vec3), asCALL_CDECL_OBJFIRST));
   asCHECK(m_engine->RegisterObjectMethod("vec3", "string str()", asFUNCTIONPR(glm::to_string, (const glm::vec3&), std::string), asCALL_CDECL_OBJLAST));

Anyone knows what might be wrong here? Also if you spot some obvious inefficiencies please let me know - vec3 is small class (it's glm::vec3) that can be copied and used by value - maybe the problem is that I return a value from Transform::get_position() instead of reference? Or that I registered vec3::opAssign as returning reference, but without it I was having errors with registers and overall breakage...

Share this post

Link to post
Share on other sites

Your opAssign methods are declared as 'const'. This is why the compiler is not able to use them for assignment.

If your vec3 class doesn't really have any pointers or anything else that needs special treatment (which I presume is the case) you may want to register the class as asOBJ_POD which would allow you to skip the registration of the destructor. This should also allow the compiler to do a bitwise copy of the vec3 rather than having to call the opAssign or copy constructor. 

If you prefer not to use asOBJ_POD for some reason, you may want to register the copy constructor instead, as it would be more efficient when creating temporary copies of a vec3 value than first creating an instance then calling opAssign.



Share this post

Link to post
Share on other sites

Thanks! To be honest I'm not sure why I didn't make it asOBJ_POD - I'm pretty sure that would be the first thing to try for me.. I tried changing it and it now compiles and seems to work fine. 

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  

  • Advertisement

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!