Returning const ref (structs) in D

Dan dbdavidson at yahoo.com
Sat Nov 24 14:22:18 PST 2012


On Saturday, 24 November 2012 at 22:01:32 UTC, Stian wrote:
> After reading that a couple of times it is a bit clearer, thank 
> you. I need to wrap my head around this. I am working on a 
> simple render/game engine, where, of course, vectors and 
> matrices are flying around.
>
> Is the compiler sophisticated enough that is it able to avoid 
> the copying. For instance, if i have a struct Matrix4x4 a = 
> node.getTransformation() and use a for whatever, but never 
> alter it, will it be able to avoid the copy? What if i declare 
> it const or immutable? Do i have to use a pointer to it?
>
> After doing some small stuff in D I am not impressed by the 
> mental mapping I am having with the memory system currently. I 
> have some more experience with high performance programs in C++ 
> and appreciate the transparency of the memory management.

To add to Johnathan's answer, with some code. As he pointed out, 
you can not have:
   Bar nonConstBar = foo.bar;
as that would be trying to make a non-const copy of something 
const with reference semantics. If that were allowed changes 
could be made to nonConstBar that would affect foo.bar which is 
const. If, however S had no pointers, dynamic arrays, associative 
arrays or members with those types, there would be no reference 
semantics and the copy of const into non-const would be fine 
(i.e. no compile error would occur).

Similarly, as stated, there is no such thing as stack reference, 
like this in C++:
   S const& s = t.s;

So, I think you can still have what you want and are familiar 
with, but you must distinguish at the point of assignment 
whenever crossing the boundary from non-const to const (and the 
reverse) for reference types. The way to do that is as you say, 
get a deep copy, but something special is required to do the deep 
copy: 
(https://github.com/patefacio/d-help/blob/master/d-help/opmix/mix.d)

Thanks
Dan

---------------------
import std.stdio;
import std.traits;
import opmix.mix;

struct Bar {
   private char[] c;
   this(this) { c = c.dup; }
}

class Foo {
   @property ref const(Bar) bar() const { return _bar; }
   this(ref const(Bar) bar) { _bar = bar.gdup; }
   private Bar _bar;
}

void moo(ref const(Bar) bar) {
   writeln("foo => ", bar);
}

void main() {
   Bar bar = { ['a','b'] };
   auto foo = new Foo(bar);
   moo(foo.bar);
   // Following fails because Bar has reference semantics
   // Compile error: conversion error from const(Bar) to Bar
   // Bar nonConstBar = foo.bar;

   // This works because gdup copies all fields recursively
   Bar nonConstBar = foo.bar.gdup;
   writeln(nonConstBar);
}



More information about the Digitalmars-d-learn mailing list