Using in as a parameter qualifier
Ali Çehreli
acehreli at yahoo.com
Fri May 31 08:58:25 PDT 2013
On 05/31/2013 02:40 AM, Shriramana Sharma wrote:
> On Fri, May 31, 2013 at 12:12 PM, Ali Çehreli <acehreli at yahoo.com> wrote:
>>> double x,y ;
>>> this () {}
>>
>> That is not allowed. In D, every type has the .init property, which
is its
>> default value.
>
> Hm can you clarify that a bit? If I actually try it I get:
>
> pair.d(14): Error: constructor pair.pair.this default constructor for
> structs only allowed with @disable and no body
For structs, the default value of an object is required to be known at
compile time, which is its default value. To enforce that rule, the
default constructor cannot be provided for structs.
What the error message is saying is that you can declare it just to
disable its use:
struct Pair {
double x = 10.75;
double y = 20.25;
// Default constructor disabled
@disable this();
// Users must use another constructor:
this(double x, double y) { this.x = x; this.y = y; }
}
As you see, you must also provide a proper constructor that is
appropriate for that type.
>>> Consider a function that operates on a pair:
>>> double abs2 ( pair a ) { return a.x * a.x + a.y * a.y ; }
>>> In C++ the function signature would be: double abs2 ( const pair & a )
>>> So I thought const ref pair a would be appropriate in D -- is that
right?
>>
>> Yes:
>> double abs2(ref const(Pair) a) { /* ... */ }
>
> But is this the idiomatic D way of doing things? I mean, would one
> normally prefer in or ref const(T) which somehow seems more awkward
> than even const T &?
Although 'in' feels like it would make all the sense for an in-parameter
(at least because it conveys our intent to the compiler), Jonathan
explained why 'in' is disappointing.
I still use 'in' in the examples in many chapters, which needs to be
corrected at some point:
http://ddili.org/ders/d.en/function_parameters.html
I gave a talk at DConf 2013, which included D's move semantics (starting
on slide 11):
http://dconf.org/talks/cehreli.html
Interestingly, that talk is already old :) due to the improvements in
dmd 2.063. Here is an adaptation of an example on the dmd 2.063 changelog:
import std.stdio;
struct S
{
this(int i) { writeln("1"); }
this(int i) const { writeln("2"); }
this(int i) immutable { writeln("3"); }
this(int i) shared { writeln("4"); }
}
void main()
{
auto a = new S; // writes "1"
auto b = new const S; // writes "2"
auto c = new immutable S; // writes "3"
auto d = new shared S; // writes "4"
}
D's move semantics are explained in the following blog posts by Bartosz
Milewski:
http://bartoszmilewski.com/2008/10/18/who-ordered-rvalue-references-part-1/
http://bartoszmilewski.com/2008/10/26/who-ordered-rvalue-references-part-2/
http://bartoszmilewski.com/2008/11/03/who-ordered-rvalue-references-part-3/
So, I would use 'ref const' only in special cases and only after
profiling proves that there would be no performance penalty for doing
that. After all, ref is implemented by a pointer and the indirect access
to the members of the object through that pointer may be slow depending
on the application. That indirection may even cause the CPU access
outside of its caches, which is a relatively very slow operation.
However, my short tests on this has demonstrated that by-ref is faster
with today's dmd even on a contrived program that accesses to random
elements of huge arrays.
However, :) if you are going to make a copy of the argument anyway,
always take a struct by-value. That works with both lvalue and rvalue
arguments and in the case of rvalues, you will get the automatic move
semantics.
My choice is by-value for structs unless there is any reason not to.
Also note that by-ref-to-const is an anti-idiom even in C++ even in
surprising places. Everybody defines operator= by taking reference to
const, which may be slower than taking by-value. This is the idiomatic
way of writing operator= in C++:
Foo & operator= (Foo that)
{
this->swap(that);
return *this;
}
> it makes optimization sense to not copy it but just automatically
provide a
> reference to it right?
Unless the language makes a guarantee about that we cannot take the
address of the parameter and save it. We wouldn't know whether it is a
copy or a reference.
> So I would expect in to mean const ref -- doesn't it work that way,
and if
> not, why not?
Another reason is less surprise because structs have copy semantics by
default.
Ali
More information about the Digitalmars-d-learn
mailing list