www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Error: mutable method isolated.graphics.g3d.model.Model.begin is not

reply Begah <mathieu.roux222 gmail.com> writes:
I have a pretty weird error : Error: mutable method 
isolated.graphics.g3d.model.Model.begin is not callable using a 
const object

The weird part is that i do not use const or immutable objects in 
my code ( for the Model ) :
struct Handle {
	Model *asset = null;
	string asset_name = null;
		
	alias asset this;
		
	 property bool initialized() {
		return asset !is null;
	}
		
	this(this) {
		(*referenceCount)++;
	}
		
	~this() {
		(*referenceCount)--;
	}
	
	size_t *referenceCount;
}

This structure is where the reference is kept ( allocated with 
c's malloc )
Then in my code, i have a loop as such :
ModelInstance[][Handle] instances;

foreach(ref model, ref instances; this.instances) {
	model.begin();
	foreach(instance; instances) {
		instance.render();
	}
	model.end();
}

But for both model.begin or model.end i get that compilation 
error.

As you can see, i am calling model.begin ( which extends to 
model.asset.begin ) but no const instances are used.

Side note :
When i remove the ref in the for loop :
foreach(model, ref instances; this.instances)

The codes compile and work, i don't understand why being a 
reference or not is a problem.
Jun 06 2016
parent reply Alex Parrill <initrd.gz gmail.com> writes:
On Monday, 6 June 2016 at 20:40:12 UTC, Begah wrote:
 I have a pretty weird error : Error: mutable method 
 isolated.graphics.g3d.model.Model.begin is not callable using a 
 const object

 [...]
It may infer const from the type of `this.instance`, which may be further modified if the method you are running this in is `const`. If you explicitly specify the type of the foreach loop variables, does it work?
Jun 06 2016
parent reply Begah <mathieu.roux222 gmail.com> writes:
On Monday, 6 June 2016 at 21:09:41 UTC, Alex Parrill wrote:
 On Monday, 6 June 2016 at 20:40:12 UTC, Begah wrote:
 I have a pretty weird error : Error: mutable method 
 isolated.graphics.g3d.model.Model.begin is not callable using 
 a const object

 [...]
It may infer const from the type of `this.instance`, which may be further modified if the method you are running this in is `const`. If you explicitly specify the type of the foreach loop variables, does it work?
Seems that it does : ModelInstance[][ModelType] instances; void render() { checkError(); shader.bind(); camera.update(); shader.uniform("uView", camera.viewMatrix); shader.uniform("uProjection", camera.projectionMatrix); foreach(ref ModelType model, ref instances; this.instances) { model.begin(); foreach(instance; instances) { instance.render(); } model.end(); } shader.unbind(); checkError(); } Adding the type to the loop gives me the error : index must be type const(Handle), not Handle. So why does it think that from the associative array that ModelType should be const? Does the key of a associative array will be const if the reference is requested?
Jun 06 2016
parent reply Alex Parrill <initrd.gz gmail.com> writes:
On Monday, 6 June 2016 at 21:16:18 UTC, Begah wrote:
 Does the key of a associative array will be const if the 
 reference is requested?
That's probably what it is, actually. Modifying the key with the ref could cause the hash of the key to change without the hashtable knowing about it, causing it to break. You might be able to get away with casting the const away, if you are sure it won't modify the hash or equality check.
Jun 06 2016
next sibling parent Begah <mathieu.roux222 gmail.com> writes:
On Monday, 6 June 2016 at 21:25:16 UTC, Alex Parrill wrote:
 On Monday, 6 June 2016 at 21:16:18 UTC, Begah wrote:
 Does the key of a associative array will be const if the 
 reference is requested?
That's probably what it is, actually. Modifying the key with the ref could cause the hash of the key to change without the hashtable knowing about it, causing it to break. You might be able to get away with casting the const away, if you are sure it won't modify the hash or equality check.
Thanks for the help, i'll just cast away the const
Jun 06 2016
prev sibling parent reply ag0aep6g <anonymous example.com> writes:
On 06/06/2016 11:25 PM, Alex Parrill wrote:
 You might be able to get away with casting the const away, if you are
 sure it won't modify the hash or equality check.
Casting away const and then mutating has undefined behavior. The compiler is free to assume that it doesn't happen. Be aware that you're working outside of the specified language if you do it. You rely on the compiler producing code that works in your favor when it has no obligation to do so. I don't think we should ever suggest relying on undefined behavior here in D.learn.
Jun 06 2016
parent Alex Parrill <initrd.gz gmail.com> writes:
On Monday, 6 June 2016 at 21:55:00 UTC, ag0aep6g wrote:
 On 06/06/2016 11:25 PM, Alex Parrill wrote:
 You might be able to get away with casting the const away, if 
 you are
 sure it won't modify the hash or equality check.
Casting away const and then mutating has undefined behavior. The compiler is free to assume that it doesn't happen. Be aware that you're working outside of the specified language if you do it. You rely on the compiler producing code that works in your favor when it has no obligation to do so. I don't think we should ever suggest relying on undefined behavior here in D.learn.
Yes, you are correct. I was mixing up C const rules with D. Unfortunately there does not seem to be an easy solution to this problem. The best solution might be to use an array of pairs instead of a hash table, but that may have a performance impact.
Jun 07 2016