Advertisement

Left-to-right Evaluation of opEquals method.

Started by February 23, 2017 04:01 PM
2 comments, last by WitchLord 7 years, 8 months ago

I have a bit of an odd construct in my application which is at odds with a change made in revision 2358 to the compiler. I have registered a value type. This value type contains configuration information for an application variable. The assignment operator for this type modifies the underlying application variable, not the script variable. For instance (something similar to this):


MyValueType& MyValueType::opAssign(double x)
{
    m_pApplicationVariable->SetValue(x);
    return *this;
}

MyValueType& MyValueType::opAssign(const MyValueType& x)
{
    opAssign(x.m_pApplicationVariable->GetValue());
    return *this;
}

I also have a comparison operator registered which compares a value to the application variable.


bool MyValueType::opEquals(double x)
{
    return m_pApplicationVariable->GetValue() == x;
}

My problem occurs when I try to compare an instance of this value type. With the new left-to-right evaluation order for overloaded operators, a temporary variable is created for my value type object. Unfortunately, the constructor isn't capable of setting up the configuration to my application variable, so when the assignment operator is called, my application generates an access violation.


// declared earlier: MyValueType my_val 

if (my_val == 3.5)

// generates...

MyValueType::MyValueType()  // temporary variable
MyValueType& MyValueType::opAssign(const MyValueType&inout)  // <-- crash
bool MyValueType::opEquals(double) // comparison with temporary variable
MyValueType::~MyValueType()  // destruction of temporary variable

How do you recommend I handle this? Script writers cannot generate these objects directly. Before using them they must be passed to an application function for configuration.

Adding a working copy constructor to the MyValueType should resolve this.

Or make MyValueType be a reference type instead.

AngelCode.com - game development and more - Reference DB - game developer references
AngelScript - free scripting library - BMFont - free bitmap font generator - Tower - free puzzle game

Advertisement

Even in the case where an opEquals method takes a constant reference to an argument, the compiler will create a copy. For large objects, this seems wasteful in the common case. Would you consider a library, compile-time setting to not ensure left-to-right evaluation? This would allow script writers to treat "==" like a direct call to opEquals.

In C++ all the overloaded operators in a class evaluate the argument list first, effectively making them evaluate right-to-left. I understand that AngelScript already differs from C++ in the handling of operators, and some of those differences may justify an "always left-to-right" evaluation requirement. For instance, with a single opEquals overload, AngelScript will allow comparisons using that object when it appears on either the right or left side of the "==" operator; C++ only compiles if the object is on the left.

Large objects should not be value types to begin, with so I don't worry too much about this wasting time.

With AngelScript I try to keep a consistent behaviour as much as possible from the view point of the script writer. This does sometimes require sacrificing performance. This is a different mentality than that used to design C++, where the language is all about trying to provide as much power to the user as possible with as little overhead as possible. In C++ runtime behaviour is explicitly undefined in the standard to give the compiler vendors more freedom to optimize the output.

I'll consider adding a flag to relax the left-to-right evaluation, however. I don't think it would add too much complexity in to the compiler.

AngelCode.com - game development and more - Reference DB - game developer references
AngelScript - free scripting library - BMFont - free bitmap font generator - Tower - free puzzle game

This topic is closed to new replies.

Advertisement