On 05/31/2013 02:40 AM, Shriramana Sharma wrote:

> On Fri, May 31, 2013 at 12:12 PM, Ali Çehreli <acehr...@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

Reply via email to