Const ref and rvalues again...

martin kinke at libero.it
Wed Nov 7 07:01:24 PST 2012


On Wednesday, 7 November 2012 at 10:33:03 UTC, Timon Gehr wrote:
> You are still missing that const in C++ is different from const 
> in D.
> const in C++ does not mean anything. It is just loosely 
> enforced interface documentation. const in D actually restricts 
> what the callee can do with the argument, in a transitive 
> fashion.

I still don't get the big difference (except for transitiveness 
for pointers). Given a const reference, I'm only able to invoke 
methods decorated with the const keyword (or inout in D) keyword, 
both in C++ and D. And I can only pass it as argument by ref to 
functions which do not alter it (also taking a const reference, 
that is).

> Also, if the point is to have higher speed, why shouldn't the 
> function be allowed to use an rvalue as scratch space without a 
> _deep copy_ ?

I'm sorry but I don't get what you mean here. Could you please 
elaborate on this?

> When my struct does not support any operations that are const, 
> and creating a mutable copy is not possible due to indirections?

If your struct doesn't support any const operations, it most 
likely has good reasons not to.

> The change may well be visible...

True in this case, but only if you know exactly what foo() does 
when you call it inside the main() function. And that is probably 
an indicator for bad encapsulation - most of the time, you 
shouldn't have the knowledge how foo() is exactly implemented 
when using it from the outside.
It is clear that there are some examples where you want to pass 
an rvalue argument to a mutable ref parameter if you know exactly 
what the function does. But imo these cases are very rare and I 
don't really regard it as big issue if you need to add a line 
'auto tmp = myRvalue;' before the function call to transform it 
to a referenceable lvalue, in these few cases.
Much more commonly, you need a parameter just as read-only input. 
Consider a real-word-example of a 4x4 matrix consisting of 16 
doubles (128 bytes). Most of the time, you'd only need a 
read-only input instance when working with it (combining 
matrices, transforming vectors etc.). Given its size (it's not 
really huge, I acknowledge that ;)), you probably want to avoid 
copying it around and therefore pass it by ref, but want that to 
also work for rvalues (produced by matrix combinations like 
'viewMatrix * modelMatrix', for example).

struct Matrix
{
     double[16] data;

     // this op= other
     ref Matrix opOpAssign(string op)(in ref Matrix other);

     // Matrix result = this op other
     Matrix opBinary(string op)(in ref Matrix other) const;

     // double4 result = this * vector
     // the vector (32 bytes) may be passed by value for AVX
     double4 opBinary(string op)(in ref double4 vector) const
         if (op == "*");
};


More information about the Digitalmars-d mailing list