Jump to page: 1 2 3
Thread overview
Efficiently passing structs
May 04, 2015
bitwise
May 04, 2015
rsw0x
May 04, 2015
bitwise
May 04, 2015
rsw0x
May 04, 2015
Baz
May 04, 2015
Jonathan M Davis
May 05, 2015
bitwise
May 05, 2015
rsw0x
May 05, 2015
bitwise
May 05, 2015
rsw0x
May 05, 2015
bitwise
May 05, 2015
Ali Çehreli
May 05, 2015
bitwise
May 06, 2015
Charles Hixson
May 06, 2015
Ali Çehreli
May 05, 2015
Jonathan M Davis
May 05, 2015
bitwise
May 05, 2015
Namespace
May 05, 2015
bitwise
May 05, 2015
Gomen
May 05, 2015
bitwise
May 05, 2015
Namespace
May 05, 2015
bitwise
May 04, 2015
If I have a large struct that needs to be passed around, like a 4x4 matrix for example, how do I do that efficiently in D?

In std.datetime, "in" is used for most struct parameters, but I'm confused by the docs for function parameter storage classes[1].

In C++, I would pass a large struct as (const&):
void foo(const Matrix4x4 &m);

Is "in" in D the same as passing by const& in C++? The documentation doesn't say anything about "in" being a reference, but it doesn't say that "out" parameters are references either, even though it's usage in the example clearly shows that it is.

Thanks,
  Bit

http://dlang.org/function.html#parameters
May 04, 2015
On Monday, 4 May 2015 at 01:58:12 UTC, bitwise wrote:
> If I have a large struct that needs to be passed around, like a 4x4 matrix for example, how do I do that efficiently in D?
>
> In std.datetime, "in" is used for most struct parameters, but I'm confused by the docs for function parameter storage classes[1].
>
> In C++, I would pass a large struct as (const&):
> void foo(const Matrix4x4 &m);
>
> Is "in" in D the same as passing by const& in C++? The documentation doesn't say anything about "in" being a reference, but it doesn't say that "out" parameters are references either, even though it's usage in the example clearly shows that it is.
>
> Thanks,
>   Bit
>
> http://dlang.org/function.html#parameters

Use the ref storage class. You can use more than one storage class i.e,

foo(in ref int x)

Unless I misunderstood you.
May 04, 2015
On Monday, 4 May 2015 at 01:58:12 UTC, bitwise wrote:
> The documentation doesn't say anything about "in" being a reference, but it doesn't say that "out" parameters are references either, even though it's usage in the example clearly shows that it is.
>
> Thanks,
>   Bit
>
> http://dlang.org/function.html#parameters

it's specified in http://dlang.org/abi.html (at the bottom):

"out and ref are passed as pointers".

The logic seems to be that if it's not specified then it's copied.

Maybe `const ref` is what you're looking for...passed as pointer but the compiler will prevent writing the parameter, though it's still possible to take the address and to modify the param if the function is not @safe.

May 04, 2015
On Sun, 03 May 2015 22:37:52 -0400, rsw0x <anonymous@anonymous.com> wrote:
> Use the ref storage class. You can use more than one storage class i.e,
> foo(in ref int x)

Thanks, this should work.


On Sun, 03 May 2015 23:29:59 -0400, Baz <bb.temp@gmx.com> wrote:
> it's specified in http://dlang.org/abi.html (at the bottom):
>
> "out and ref are passed as pointers".

Awesome, thanks for the link.

> Maybe `const ref` is what you're looking for...

I'll probably go with "in ref". I think "escape proof" is probably a good default. Not to mention, easier to type ;)
May 04, 2015
On Monday, 4 May 2015 at 03:57:04 UTC, bitwise wrote:
> I'll probably go with "in ref". I think "escape proof" is probably a good default. Not to mention, easier to type ;)

FYI I'm unsure how well `scope` storage class is currently implemented because it's in a state of flux at the moment as far as I know. `in ref` still helps document your intent of the parameter however.

It's hard to track this down exactly because scope has so many different meanings in D, making it difficult to search for - at least one of them has been deprecated.
May 04, 2015
On Sunday, May 03, 2015 21:58:12 bitwise via Digitalmars-d-learn wrote:
> If I have a large struct that needs to be passed around, like a 4x4 matrix for example, how do I do that efficiently in D?
>
> In std.datetime, "in" is used for most struct parameters, but I'm confused by the docs for function parameter storage classes[1].
>
> In C++, I would pass a large struct as (const&):
> void foo(const Matrix4x4 &m);
>
> Is "in" in D the same as passing by const& in C++? The documentation doesn't say anything about "in" being a reference, but it doesn't say that "out" parameters are references either, even though it's usage in the example clearly shows that it is.
>
> Thanks,
>    Bit
>
> http://dlang.org/function.html#parameters

std.datetime's use of in is pointless and really should be removed. I misunderstood it at the time I did that. in is essentially an alias for const scope, and scope does nothing in most cases, basically making it const, which is generally pointless for a function parameter unless you're specifically trying to make it so that it can't be mutated inside the function. And since scope has not even been properly designed (let alone implemented), I would argue that using in is almost always a bad idea.

The equivalent to const& in D is const ref except that it does not accept rvalues. So, if you want to be able to do the same, you'll have to do something like

void foo(ref const Matrix4x4 m)
{
    ...
}

void foo(const Matrix4x4 m)
{
    foo(m);
}

D will move the argument if it can rather than copying it (e.g. if a temporary is being passed in), which reduces the need for worrying about copying like you tend to have to do in C++98, and I think that a lot of D code just doesn't worry about the cost of copying structs. However, if you have a large object that you know is going to be expensive to copy, you're either going to have to use const ref (and thus probably duplicate the function to allow rvalues), or you're going to need to make it a reference type rather than having all of its data live on the stack (either by making it so that the struct contains a pointer to its data or by making it a class). In general, if you're dealing with a type that is going to be expensive to copy, I'd advise making it a reference type over relying on const ref simply because it's less error-prone that way. It's trivial to forget to use ref on a parameter, and generic code won't use it, so it'll generally work better to just make it a reference type.

- Jonathan M Davis

May 05, 2015
On Mon, 04 May 2015 00:16:03 -0400, Jonathan M Davis via Digitalmars-d-learn <digitalmars-d-learn@puremagic.com> wrote:
> D will move the argument if it can rather than copying it (e.g. if a
> temporary is being passed in), which reduces the need for worrying about
> copying like you tend to have to do in C++98, and I think that a lot of D
> code just doesn't worry about the cost of copying structs.

How exactly would you move a struct? Just a memcpy without the postblit?

> However, if you have a large object that you know is going to be
> expensive to copy, you're either going to have to use const ref
> (and thus probably duplicate the function to allow rvalues), or
> you're going to need to make it a reference type rather than
> having all of its data live on the stack (either by making
> it so that the struct contains a pointer to its data or by making it a
> class).
> In general, if you're dealing with a type that is going to be
> expensive to copy, I'd advise making it a reference type over relying on
> const ref simply because it's less error-prone that way. It's trivial to
> forget to use ref on a parameter, and generic code won't use it, so it'll
> generally work better to just make it a reference type.
>
> - Jonathan M Davis

Something like a Matrix4x4 lives in an awkward place between a class and a struct. Because of the fact that a graphics engine may have to deal with thousands of them per frame, both copying them at function calls, and allocating/collecting thousands of them per frame, are both unacceptable.

I was reading up(DIP36, pull requests, forum) and it seems like auto ref was supposed to do something like this. Is there a reason you didn't mention it?

Why not just add "rvref" to D?

"rvref" would be the same as ref, but would accept an lvalue or an rvalue without copying. You could make it const, scope, or whatever you want. It would be unsafe if used incorrectly, but thats what regular "ref" is for. I suppose additional security could be added though, like making "rvref" escape-proof by default. This would introduce no breaking changes and facilitate efficient passing of structs.

  Bit
May 05, 2015
On Tuesday, 5 May 2015 at 02:47:03 UTC, bitwise wrote:
> On Mon, 04 May 2015 00:16:03 -0400, Jonathan M Davis via Digitalmars-d-learn <digitalmars-d-learn@puremagic.com> wrote:
>> D will move the argument if it can rather than copying it (e.g. if a
>> temporary is being passed in), which reduces the need for worrying about
>> copying like you tend to have to do in C++98, and I think that a lot of D
>> code just doesn't worry about the cost of copying structs.
>
> How exactly would you move a struct? Just a memcpy without the postblit?
>
>> However, if you have a large object that you know is going to be
>> expensive to copy, you're either going to have to use const ref
>> (and thus probably duplicate the function to allow rvalues), or
>> you're going to need to make it a reference type rather than
>> having all of its data live on the stack (either by making
>> it so that the struct contains a pointer to its data or by making it a
>> class).
>> In general, if you're dealing with a type that is going to be
>> expensive to copy, I'd advise making it a reference type over relying on
>> const ref simply because it's less error-prone that way. It's trivial to
>> forget to use ref on a parameter, and generic code won't use it, so it'll
>> generally work better to just make it a reference type.
>>
>> - Jonathan M Davis
>
> Something like a Matrix4x4 lives in an awkward place between a class and a struct. Because of the fact that a graphics engine may have to deal with thousands of them per frame, both copying them at function calls, and allocating/collecting thousands of them per frame, are both unacceptable.
>
> I was reading up(DIP36, pull requests, forum) and it seems like auto ref was supposed to do something like this. Is there a reason you didn't mention it?

it does, auto ref can bind to both lvalues and rvalues. Create the function with an empty template like so,

import std.stdio;

struct S{
}

void Foo()(auto ref S s){
}

void main(){
	S s;
	Foo(s);
	Foo(S());
}

There might be other ways that I'm unaware of.

>
> Why not just add "rvref" to D?

D is already bloated.
May 05, 2015
On Tue, 05 May 2015 00:20:15 -0400, rsw0x <anonymous@anonymous.com> wrote:
> it does, auto ref can bind to both lvalues and rvalues. Create the function with an empty template like so,
>
> import std.stdio;
>
> struct S{
> }
>
> void Foo()(auto ref S s){
> }
>
> void main(){
> 	S s;
> 	Foo(s);
> 	Foo(S());
> }
>
> There might be other ways that I'm unaware of.

Interesting.. Has this always worked? Theres a couple of forum conversations about trying to get "auto ref" to work for non-templates. The main problem seems to be that auto ref wont work for virtual functions. Also, I don't see how someone could arrive at the above solution without showing up here and asking first.

>> Why not just add "rvref" to D?
>
> D is already bloated.

Some of the discussions about auto ref seem to have arrived at the idea that adding a keyword is the only way fix this without changing existing behavior or adding new behavior that would share syntax with old behavior and be confusing.

Anyways, for my purposes, templates will do fine, so thanks!

  Bit
May 05, 2015
On Tuesday, 5 May 2015 at 14:14:51 UTC, bitwise wrote:
> On Tue, 05 May 2015 00:20:15 -0400, rsw0x <anonymous@anonymous.com> wrote:
>> it does, auto ref can bind to both lvalues and rvalues. Create the function with an empty template like so,
>>
>> import std.stdio;
>>
>> struct S{
>> }
>>
>> void Foo()(auto ref S s){
>> }
>>
>> void main(){
>> 	S s;
>> 	Foo(s);
>> 	Foo(S());
>> }
>>
>> There might be other ways that I'm unaware of.
>
> Interesting.. Has this always worked? Theres a couple of forum conversations about trying to get "auto ref" to work for non-templates. The main problem seems to be that auto ref wont work for virtual functions.

I know its worked for a while, I often use it when I'm too lazy to put attributes in and just have the templates infer them for me ;)

> Also, I don't see how someone could arrive at the above solution without showing up here and asking first.
>

You're probably right, maybe someone should submit a PR to https://github.com/p0nce/d-idioms/
« First   ‹ Prev
1 2 3