Advertisement

Property setter compile problem

Started by July 11, 2016 04:29 AM
10 comments, last by WitchLord 8 years, 4 months ago

Hello!

This code isn't compile with an error

<<<'test' is not declared>>>

at the line if(test != nTest) {


class Base {
    private int m_test;

    void set_test(int nTest) {
        m_test = nTest;
    }
    int get_test() {
        return m_test;
    }
}

class Derived : Base {
    private int m_numChanges;

    void set_test(int nTest) override {
        if(test != nTest) {
            Base::set_test(nTest);
            m_numChanges++;
        }
    }
}

And to allow the code above to be compiled it's necessary to change the row to

if(get_test() != nTest) {

It seems there's a bug in compiler causing this problem.

Thanks!

It's not a compiler bug, test is simply not declared. You probably meant m_test. Also you probably will never find a compiler bug with trivial code like this. There are probably a few million other users of your compiler. If an if statement in a method wouldn't work, it would already be fixed. If you still want to blame the compiler, I suggest compiling your code with a different compiler. If it still doesn't compile, it's nearly impossible, that it's a bug in the compiler.
Advertisement

It's not a compiler bug, test is simply not declared. You probably meant m_test. Also you probably will never find a compiler bug with trivial code like this. There are probably a few million other users of your compiler. If an if statement in a method wouldn't work, it would already be fixed. If you still want to blame the compiler, I suggest compiling your code with a different compiler. If it still doesn't compile, it's nearly impossible, that it's a bug in the compiler.

Well... we speak here about AngelScript language. ;-)

And if you read AS docs there's a topic named "Property accessors".

So in AngelScript

int a = classInstance.test is equivalent to

int a = classInstance.get_test()

And this really works everywhere.

But doesn't work inside the overloaded "setter" method. And I have strong feeling it's a bug.

Regarding the "compiling your code with a different compiler": I'm afraid there's no other compiler supporting this AS feature, unfortunately.

Try making the get method const. The documentation uses const methods, so there might be an unexpected bug there with non-const versions.

Ah, sorry, I really messed up, in which forum I was and misread the question, way to go! Sorry about the confusion.

Still, I don't know that much about AS, but from your explanaition shouldn't get_test() be get_m_test() if you want to overload the getter?

Ah, sorry, I really messed up, in which forum I was and misread the question, way to go! Sorry about the confusion.

Still, I don't know that much about AS, but from your explanaition shouldn't get_test() be get_m_test() if you want to overload the getter?

No problem about the confusion.

"get_test()" and "test" should be 100% equivalent by design, but they are not as I wrote above.

And I override only setter, not getter. When I call parent getter via "test" from this setter - this doesn't work.

Advertisement

Try making the get method const. The documentation uses const methods, so there might be an unexpected bug there with non-const versions.

Tried.

Got the same compiler error: <<<'test' is not declared>>>

I checked the compiler, and i think i found the cause. In asCCompiler::FindPropertyAccessor, the compiler explicitly checks if it's inside of a member function and pretends the getter doesn't exist:


// Avoid recursive call, by not treating this as a property accessor call.
	// This will also allow having the real property with the same name as the accessors.
	if( (isThisAccess || outFunc->objectType == 0) &&
		((realGetId && realGetId == outFunc->id) ||
		 (realSetId && realSetId == outFunc->id)) )
	{
		getId = 0;
		setId = 0;
	}

realSetId is equal to the outFunc->id member, so getId is zeroed out, which means it couldn't find it. outFunc is the function currently being compiled.

I suppose it should allow access if you're in a setter and accessing a getter belonging to the setter's property, but as the comment notes, there is a possible recursion issue here. If the base class calls the setter in the getter, and the derived class setter calls the getter, it could end up in an infinite loop.

So it should only allow setter->getter access, but not getter->setter access.

To avoid this issue, you could make the base member protected and access that. Alternatively, make a protected property that gets and sets the member and then use that.

This looks like intended behavior. After a quick test, it appears that the language allows you to use if (this.test != nTest), which, I think, is less ambiguous than just test anyway, making it clearer that you're using a property accessor but not being explicit about it.

So it should only allow setter->getter access, but not getter->setter access.

To avoid this issue, you could make the base member protected and access that. Alternatively, make a protected property that gets and sets the member and then use that.

I currently use get_test() and it works so I only tried to understand it's a compiler bug or something other.

And because there's nothing regarding this in docs I decided it's a bug.

So thank you for explanation!

This topic is closed to new replies.

Advertisement