www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Why do I get this error when casting to an immutable or shared byRef

reply Gary Willoughby <dev nomad.so> writes:
In the following code, the `foo` function doesn't work when 
casting to an immutable or shared type. Can anyone please explain 
what is happening here? Is there any way of returning such 
variables byRef from a malloc'd chunk of memory?

import core.stdc.stdlib;

ref T foo(T)()
{
	int* foo = cast(int*) malloc(int.sizeof * 8);

	return *foo;
}

void main(string[] args)
{
	// Works!
	auto bar = foo!(int)();

	// Works!
	auto bar = foo!(const(int))();

	// Error: cast(immutable(int))*foo is not an lvalue
	auto bar = foo!(immutable(int))();

	// Error: cast(shared(int))*foo is not an lvalue
	auto bar = foo!(shared(int))();
}
Jun 19 2016
parent reply Gary Willoughby <dev nomad.so> writes:
On Sunday, 19 June 2016 at 10:35:59 UTC, Gary Willoughby wrote:
 ...
A more correct example: import core.stdc.stdlib; import std.traits; ref T foo(T)() { alias Type = Unqual!(T); Type* foo = cast(Type*) malloc(Type.sizeof * 8); return *foo; } void main(string[] args) { // Works! auto bar = foo!(int)(); // Works! auto bar = foo!(const(int))(); // Error: cast(immutable(int))*foo is not an lvalue auto bar = foo!(immutable(int))(); // Error: cast(shared(int))*foo is not an lvalue auto bar = foo!(shared(int))(); }
Jun 19 2016
next sibling parent Mike Parker <aldacron gmail.com> writes:
On Sunday, 19 June 2016 at 10:45:25 UTC, Gary Willoughby wrote:
 On Sunday, 19 June 2016 at 10:35:59 UTC, Gary Willoughby wrote:
 ...
A more correct example:
In the second example, the problem is this: alias Type = Unqual!(T); You are declaring the function to return T, which in your example is either int, const(int), immutable(int), or shared(int), but are returning a plain int in every case. This is fine for const(int), since non-const can implicitly convert to const. That is not the case for immutable(int) or shared(int). If you take out the alias to Unqual!T and replace both remaining instances of Type with T, then it works.
Jun 19 2016
prev sibling parent ag0aep6g <anonymous example.com> writes:
On 06/19/2016 12:45 PM, Gary Willoughby wrote:
 On Sunday, 19 June 2016 at 10:35:59 UTC, Gary Willoughby wrote:
 ...
A more correct example: import core.stdc.stdlib; import std.traits; ref T foo(T)() { alias Type = Unqual!(T); Type* foo = cast(Type*) malloc(Type.sizeof * 8); return *foo; } void main(string[] args) { // Works! auto bar = foo!(int)(); // Works! auto bar = foo!(const(int))(); // Error: cast(immutable(int))*foo is not an lvalue auto bar = foo!(immutable(int))(); // Error: cast(shared(int))*foo is not an lvalue auto bar = foo!(shared(int))(); }
At the core, int* doesn't implicitly convert to immutable(int)*. Equally, a mutable int doesn't implicitly convert to an immutable one with the same address. That conversion makes a copy, so the result is an rvalue and you can't take it's address. A mutable int does implicitly convert to a const one with the same address, because const is fine with the value changing through the mutable view. immutable would not be fine with that, so it's rejected. Same with shared, of course.
Jun 19 2016