Jump to page: 1 2
Thread overview
Passing structs to functions
Jul 02, 2016
phant0m
Jul 02, 2016
ketmar
Jul 02, 2016
phant0m
Jul 02, 2016
H. S. Teoh
Jul 02, 2016
ketmar
Jul 02, 2016
phant0m
Jul 02, 2016
Namespace
Jul 02, 2016
ketmar
Jul 02, 2016
Namespace
Jul 02, 2016
ketmar
Jul 02, 2016
Namespace
Jul 03, 2016
Adam D. Ruppe
Jul 02, 2016
Namespace
Jul 02, 2016
Adam D. Ruppe
Jul 02, 2016
phant0m
Jul 02, 2016
Adam D. Ruppe
Jul 02, 2016
ketmar
July 02, 2016
I came from a C++ world, so I'm used to passing structs by a const reference (I mean the case, where a function argument isn't changed by the function). C++ allows passing a temporary (rvalue) to a function, which accepts a const reference. D doesn't allow this. All I have found is a message from Andrei: http://digitalmars.com/d/archives/digitalmars/D/const_ref_rvalues_103509.html#N103514 Sadly, he didn't describe the details there. Let's suppose he's right.
How should I pass a struct variable in D effectively? When passing by a const reference, I need to implement 2^N additional overloads, where N is the number of arguments. On the other hand, passing by value can be very ineffective.
Maybe I shouldn't bother at all and a compiler is smart enough to always optimize variables passed by value?
Please, share your best practices. There are many options here (immutable, const, ref, in, out, inout) and I don't know what I should prefer.
July 02, 2016
void boo() (in auto ref MyStruct s) { ... }

this will accept both lvalues and rvalues, and will avoid copying if it can.
July 02, 2016
On Saturday, 2 July 2016 at 18:43:51 UTC, ketmar wrote:
> void boo() (in auto ref MyStruct s) { ... }
>
> this will accept both lvalues and rvalues, and will avoid copying if it can.

Thank you! Could you please explain what does "auto" in this context mean?
July 02, 2016
On Sat, Jul 02, 2016 at 06:47:31PM +0000, phant0m via Digitalmars-d-learn wrote:
> On Saturday, 2 July 2016 at 18:43:51 UTC, ketmar wrote:
> > void boo() (in auto ref MyStruct s) { ... }
> > 
> > this will accept both lvalues and rvalues, and will avoid copying if it can.
> 
> Thank you! Could you please explain what does "auto" in this context mean?

It's actually "auto ref", which roughly means "automatically decide whether it's more efficient to pass by value or pass by ref". The compiler will decide whether or not to pass by ref.


T

-- 
Life is too short to run proprietary software. -- Bdale Garbee
July 02, 2016
On Saturday, 2 July 2016 at 18:47:31 UTC, phant0m wrote:
> On Saturday, 2 July 2016 at 18:43:51 UTC, ketmar wrote:
>> void boo() (in auto ref MyStruct s) { ... }
>>
>> this will accept both lvalues and rvalues, and will avoid copying if it can.
>
> Thank you! Could you please explain what does "auto" in this context mean?

basically, what you think it does. ;-)

it means "use ref if you can, but fallback to copy if you can't". so it accepts both:

  MyStruct s;
  boo(s);

and

  boo(MyStruct());

note the first "()", though: this is effectively a template function, which compiler will instantiate either with "ref" or without it.
July 02, 2016
On Saturday, 2 July 2016 at 19:25:37 UTC, ketmar wrote:
> note the first "()", though: this is effectively a template function, which compiler will instantiate either with "ref" or without it.

Yeah, I've noticed it. Always using function template for this use case seems like a weird idea.
July 02, 2016
On Saturday, 2 July 2016 at 18:37:06 UTC, phant0m wrote:
> How should I pass a struct variable in D effectively?

Passing by value is often the most efficient. It depends on what exactly you have in the struct.
July 02, 2016
On Saturday, 2 July 2016 at 19:46:53 UTC, Adam D. Ruppe wrote:
> On Saturday, 2 July 2016 at 18:37:06 UTC, phant0m wrote:
>> How should I pass a struct variable in D effectively?
>
> Passing by value is often the most efficient. It depends on what exactly you have in the struct.

From the point of view of a hardcore C++ programmer, D looks very promising and very strange at the same time. I understand that my C++ habits are not applicable here, so I'm trying to find a "correct" way to do basic things.
I took a simple task (for D learning purposes): to implement a Point template "class" (something like Qt's QPoint).
As far as I want to be able to add two points, I've implemented opAdd() function:

struct Point(T) {
    static assert(__traits(isArithmetic, T));

    T x;
    T y;

    Point opAdd(const ref Point other) const {
        return Point(x + other.x, y + other.y);
    }
}


Now, to be able to use rvalues, I need to add another one:
    Point opAdd(const Point other) const {
        return opAdd(other);
    }

That's where my question came from. Of course, I can use just one function, which  accepts arguments by value. I'm just unsure whether it's a good decision and a common practice.
July 02, 2016
On Saturday, 2 July 2016 at 20:24:12 UTC, phant0m wrote:
> I took a simple task (for D learning purposes): to implement a Point template "class" (something like Qt's QPoint).


Using ref is wasteful there regardless.... just take an ordinary Point (even const is optional if it is all value but it doesn't hurt).

I think a lot of C++ programmers overuse references. If you're passing a large thing, it makes sense, but for small things it often has an overall negative effect on performance, but I see people saying they ALWAYS use struct& just out of habit.

Even if you have an array slice or class object in there in D, they are already references, so you don't want to use ref again on top of it. Most the time, you're probably ok just passing a normal T or const T.

> As far as I want to be able to add two points, I've implemented  opAdd() function:

opAdd is the old way in D, nowadays it is more like

Point opBinary(string op : "+")(const Point other) const {
      return Point(x + other.x, y + other.y);
}

July 02, 2016
On Saturday, 2 July 2016 at 19:40:53 UTC, phant0m wrote:
> On Saturday, 2 July 2016 at 19:25:37 UTC, ketmar wrote:
>> note the first "()", though: this is effectively a template function, which compiler will instantiate either with "ref" or without it.
>
> Yeah, I've noticed it. Always using function template for this use case seems like a weird idea.

Try this little trick:

----
import std.stdio;

struct A {
	private A* _this = null;
	public int id = 0;
	
	this(int id) {
		this.id = id;
	}
	
	ref A byRef() {
		_this = &this;
		
		return *_this;
	}
}

void foo(ref const A a) {
	writeln(a.id);
}

void main() {
	foo(A(42).byRef());
}
----
« First   ‹ Prev
1 2