Re: Declaring rvalue function arguments

2016-01-31 Thread Jonathan M Davis via Digitalmars-d-learn
On Sunday, January 31, 2016 17:48:53 maik klein via Digitalmars-d-learn wrote:
> On Sunday, 31 January 2016 at 17:42:19 UTC, anonymous wrote:
> > On 31.01.2016 18:21, Matt Elkins wrote:
> > I don't know if this works in all cases, but it passes that
> > simple test:
> >
> > 
> > @disable void foo(ref int x);
> > void foo(int x) {}
> >
> > void main()
> > {
> > foo(5); /* works */
> > int y = 5;
> > foo(y); /* error */
> > }
> > 
>
> The problem is that x will be copied afaik which is not what you
> want if you want to deal with ownership.

In D, if you pass an rvalue to a function or assign it to a variable, then
it's going to be moved, not copied. So by making it illegal to pass an
lvalue to a function, you guarantee that every argument it gets was moved
and not copied.

- Jonathan M Davis



Re: Declaring rvalue function arguments

2016-01-31 Thread Matt Elkins via Digitalmars-d-learn

On Sunday, 31 January 2016 at 18:02:19 UTC, Matt Elkins wrote:

Here is the one I am using right now:


Actually, here is the whole module in case you are interested in 
the unittests/usage:


[code]
import std.algorithm;
import std.traits;

struct ResourceHandle(T, alias Deleter, T Default = T.init)
{
// Constructors/Destructor
this(in T handle) {m_handle = handle;}
@disable this(this);
~this() {Deleter(m_handle);}

// Operators
@disable void opAssign(ref ResourceHandle lvalue);
ref ResourceHandle opAssign(ResourceHandle rvalue) 
{swap(m_handle, rvalue.m_handle); return this;}


// Methods
@property T handle() const {return m_handle;}
@property T handle(T handle) {Deleter(m_handle); m_handle = 
handle; return m_handle;}
T release() {T result = m_handle; m_handle = Default; return 
result;}


private:
T m_handle = Default;
}

@nogc @safe nothrow unittest
{
static uint destroyedCount;
static uint lastDestroyed;
alias RH = ResourceHandle!(uint, (uint resource){if (resource 
!= uint.init) {lastDestroyed = resource; ++destroyedCount;}});


// Test basic resource cleanup
assert(destroyedCount == 0);
assert(lastDestroyed != 7);
{auto handle0 = RH(7);}
assert(destroyedCount == 1);
assert(lastDestroyed == 7);

// Test releasing
{
auto handle0 = RH(8);
assert(handle0.handle == 8);
assert(handle0.release() == 8);
assert(handle0.handle == uint.init);
assert(destroyedCount == 1);
assert(lastDestroyed == 7);
}
assert(destroyedCount == 1);
assert(lastDestroyed == 7);

{
// Test that copying and lvalue assignment are disabled
auto handle0 = RH(5);
static assert (!__traits(compiles, {auto handle1 = 
handle0;}));
static assert (!__traits(compiles, {RH handle1; handle1 = 
handle0;}));


// Test that rvalue assignment works
auto makeRH(uint value) {return RH(value);}
handle0 = makeRH(3);
assert(destroyedCount == 2);
assert(lastDestroyed == 5);
}
assert(destroyedCount == 3);
assert(lastDestroyed == 3);

// Test setting in static array
{
RH[3] handles;
handles[0] = RH(9);
assert(destroyedCount == 3);
assert(lastDestroyed == 3);
}
assert(destroyedCount == 4);
assert(lastDestroyed == 9);

// Test setting to resource directly
{
auto handle0 = RH(11);
assert(destroyedCount == 4);
assert(lastDestroyed == 9);
assert(handle0.handle == 11);
handle0.handle = 12;
assert(destroyedCount == 5);
assert(lastDestroyed == 11);
assert(handle0.handle == 12);
}
assert(destroyedCount == 6);
assert(lastDestroyed == 12);
}
[/code]


Re: Declaring rvalue function arguments

2016-01-31 Thread Matt Elkins via Digitalmars-d-learn

On Sunday, 31 January 2016 at 17:55:53 UTC, Matt Elkins wrote:
Errr, ignore the makeFoo() line. Left that in by accident, has 
no bearing on the issue.


Ok, I think I understand why this doesn't work, at least. The Foo 
passed into bar() is, of course, an lvalue itself.


So I can achieve this with a new bar(), like so:

[code]
void bar(Foo foo)
{
import std.algorithm.mutation;
Foo foo1 = move(foo);
}
[/code]


Re: Declaring rvalue function arguments

2016-01-31 Thread Matt Elkins via Digitalmars-d-learn

On Sunday, 31 January 2016 at 17:48:53 UTC, maik klein wrote:
The problem is that x will be copied afaik which is not what 
you want if you want to deal with ownership.


I think that can be solved by wrapping the resource in a struct 
that deals with passing the ownership. Here is the one I am using 
right now:


[code]
struct ResourceHandle(T, alias Deleter, T Default = T.init)
{
// Constructors/Destructor
this(in T handle) {m_handle = handle;}
@disable this(this);
~this() {Deleter(m_handle);}

// Operators
@disable void opAssign(ref ResourceHandle lvalue);
ref ResourceHandle opAssign(ResourceHandle rvalue) 
{swap(m_handle, rvalue.m_handle); return this;}


// Methods
@property T handle() const {return m_handle;}
@property T handle(T handle) {Deleter(m_handle); m_handle = 
handle; return m_handle;}
T release() {T result = m_handle; m_handle = Default; return 
result;}


private:
T m_handle = Default;
}
[/code]


Re: Declaring rvalue function arguments

2016-01-31 Thread maik klein via Digitalmars-d-learn

On Sunday, 31 January 2016 at 17:55:53 UTC, Matt Elkins wrote:
Errr, ignore the makeFoo() line. Left that in by accident, has 
no bearing on the issue.


I have found an interesting SO answer 
http://stackoverflow.com/a/35114945/944430


This would explain everything that we would need. I am just not 
100% sure if everything he says is actually true.


Re: Declaring rvalue function arguments

2016-01-31 Thread Matt Elkins via Digitalmars-d-learn
Errr, ignore the makeFoo() line. Left that in by accident, has no 
bearing on the issue.


Re: Declaring rvalue function arguments

2016-01-31 Thread Matt Elkins via Digitalmars-d-learn

On Sunday, 31 January 2016 at 17:42:19 UTC, anonymous wrote:
I don't know if this works in all cases, but it passes that 
simple test:



@disable void foo(ref int x);
void foo(int x) {}

void main()
{
foo(5); /* works */
int y = 5;
foo(y); /* error */
}



My fault, I should have better explained the situation I'm 
running into. I've boiled it down to this:


[code]
struct Foo
{
@disable this(this);
@disable void opAssign(ref Foo);
void opAssign(Foo foo) {}
}

unittest
{
void bar(Foo foo)
{
Foo foo1;
foo1 = foo; // Fails to compile here
}
Foo makeFoo() {return Foo();}
bar(Foo());
}
[/code]

[output]
Error: function Foo.opAssign is not callable because it is 
annotated with @disable

[/output]

Note that if I don't declare and assign foo1 on separate steps it 
yells at me for the post-blit constructor being disabled, which 
is reasonable. But it seems like the rvalue assignment operator 
should work...


Re: Declaring rvalue function arguments

2016-01-31 Thread maik klein via Digitalmars-d-learn

On Sunday, 31 January 2016 at 17:42:19 UTC, anonymous wrote:

On 31.01.2016 18:21, Matt Elkins wrote:
I know I can mark an argument ref to require lvalues, so I'm 
wondering
whether there is an equivalent for rvalues; that is, is there 
a way to

specify that an argument to a function MUST be an rvalue?

For example, in C++ I can do this:
[code]
void foo(int && x) {...}

foo(5); // Works fine
int y = 5;
foo(y); // Compile error; y is not an rvalue
[/code]

This functionality turns out to be really useful when dealing 
with

transferring ownership of resources.


I don't know if this works in all cases, but it passes that 
simple test:



@disable void foo(ref int x);
void foo(int x) {}

void main()
{
foo(5); /* works */
int y = 5;
foo(y); /* error */
}



The problem is that x will be copied afaik which is not what you 
want if you want to deal with ownership.


Re: Declaring rvalue function arguments

2016-01-31 Thread anonymous via Digitalmars-d-learn

On 31.01.2016 18:21, Matt Elkins wrote:

I know I can mark an argument ref to require lvalues, so I'm wondering
whether there is an equivalent for rvalues; that is, is there a way to
specify that an argument to a function MUST be an rvalue?

For example, in C++ I can do this:
[code]
void foo(int && x) {...}

foo(5); // Works fine
int y = 5;
foo(y); // Compile error; y is not an rvalue
[/code]

This functionality turns out to be really useful when dealing with
transferring ownership of resources.


I don't know if this works in all cases, but it passes that simple test:


@disable void foo(ref int x);
void foo(int x) {}

void main()
{
foo(5); /* works */
int y = 5;
foo(y); /* error */
}



Re: Declaring rvalue function arguments

2016-01-31 Thread maik klein via Digitalmars-d-learn

On Sunday, 31 January 2016 at 17:21:54 UTC, Matt Elkins wrote:
I know I can mark an argument ref to require lvalues, so I'm 
wondering whether there is an equivalent for rvalues; that is, 
is there a way to specify that an argument to a function MUST 
be an rvalue?


For example, in C++ I can do this:
[code]
void foo(int && x) {...}

foo(5); // Works fine
int y = 5;
foo(y); // Compile error; y is not an rvalue
[/code]

This functionality turns out to be really useful when dealing 
with transferring ownership of resources.


I am also very interested in this. I just asked this question 
today on SO 
https://stackoverflow.com/questions/35115702/how-do-i-express-ownership-semantics-in-d





Declaring rvalue function arguments

2016-01-31 Thread Matt Elkins via Digitalmars-d-learn
I know I can mark an argument ref to require lvalues, so I'm 
wondering whether there is an equivalent for rvalues; that is, is 
there a way to specify that an argument to a function MUST be an 
rvalue?


For example, in C++ I can do this:
[code]
void foo(int && x) {...}

foo(5); // Works fine
int y = 5;
foo(y); // Compile error; y is not an rvalue
[/code]

This functionality turns out to be really useful when dealing 
with transferring ownership of resources.