May 31, 2013
On Friday, 31 May 2013 at 17:50:33 UTC, Shriramana Sharma wrote:
> Sorry but I still don't get it -- if a default constructor is
> disallowed for struct-s by the language itself, why should I have to
> *tell* the compiler to disable it?

The compiler always provides a default constructor (maybe not technically) which is used for .init.

By requesting the default constructor be disabled, is really saying don't let anyone declare the struct without initializing it.

Testing shows that in 2.060 the init property is still usable, which I expected as it is most useful in generic code. But I don't know if that is sticking around, it is kind of like int a = void;
May 31, 2013
On Friday, May 31, 2013 23:25:02 Jesse Phillips wrote:
> On Friday, 31 May 2013 at 17:50:33 UTC, Shriramana Sharma wrote:
> > Sorry but I still don't get it -- if a default constructor is
> > disallowed for struct-s by the language itself, why should I
> > have to
> > *tell* the compiler to disable it?
> 
> The compiler always provides a default constructor (maybe not
> technically) which is used for .init.
> 
> By requesting the default constructor be disabled, is really saying don't let anyone declare the struct without initializing it.
> 
> Testing shows that in 2.060 the init property is still usable, which I expected as it is most useful in generic code. But I don't know if that is sticking around, it is kind of like int a = void;

I believe that a disabled init property is still useable in some type inference stuff (e.g. typeof(type.init) may still work), but if init has been disabled, then you can't use that struct in any situation which requires default initialization. It's not like you get = void in the cases where init is disabled and you need init. Rather, you just can't use that type in that situation.

- Jonathan M Davis
May 31, 2013
On Sat, Jun 1, 2013 at 1:13 AM, Jonathan M Davis <jmdavisProg@gmx.com> wrote:
> Certainly,
> for anything that's small enough to fit in a register, it's likely to be faster
> to pass by value.

So pardon my ignorance, but a pair which only contains two doubles -- it would fit in a CPU register? How about a bezier class/struct which contains 4 pairs i.e. 8 doubles?

And that would mean that passing by value is faster 'cause it's cheaper to copy the data to a register and have the processor operate on it directly than to copy the pointer (which lies beneath the reference) and have the indirection and *then* copy (?) the data? (I mean I'm not sure how these things work -- even when you are using a pointer/reference, copying from the memory to CPU register is unavoidable right? C++'s const T & only makes it so that copying from memory-to-memory can be avoided, right?

-- 
Shriramana Sharma ஶ்ரீரமணஶர்மா श्रीरमणशर्मा
May 31, 2013
On Fri, May 31, 2013 at 8:55 PM, Jonathan M Davis <jmdavisProg@gmx.com> wrote:
> In D, const ref does not accept rvalues (unlike C++'s const &).

So what is the syntax that accepts rvalues and yet does not make a copy of the input object? I mean, as Ali says OK profiling is preferable to find out where exactly passing by value is more efficient than passing by const ref, but I'd like to know anyway what is the syntax available for this so at least until I get my D legs, I can continue some of my practices from C++ without much detriment.

I just finished reading this link which Ali gave: http://bartoszmilewski.com/2008/11/03/who-ordered-rvalue-references-part-3/ but perhaps due to my ignorance I don't get 100% what he is tryring to say. Is it really relevant for what I am asking, like avoiding a copy-constructor in the input of a function which will not modify its input, even if I pass by value?

I'm currently working on a project at some priority, and it's currently at a relatively flexible stage so I am thinking of switching it over to D thinking it would make me finish the job quicker, but if I will have to bend my thinking too much around differences between C++ and D and around unfinished language features (scope?) I think I may stick with C++ at least for the present project and maybe use D for future ones. Advice?

-- 
Shriramana Sharma ஶ்ரீரமணஶர்மா श्रीरमणशर्मा
June 01, 2013
On Sat, Jun 1, 2013 at 5:11 AM, Shriramana Sharma <samjnaa@gmail.com> wrote:
> So what is the syntax that accepts rvalues and yet does not make a copy of the input object? I mean, as Ali says OK profiling is preferable to find out where exactly passing by value is more efficient than passing by const ref, but I'd like to know anyway what is the syntax available for this so at least until I get my D legs, I can continue some of my practices from C++ without much detriment.

And again, sorry if I'm being dumb, but is the proposed inout syntax intended to fix this problem or some other problem? http://d.puremagic.com/issues/show_bug.cgi?id=3748 is marked as resolved fixed from back in 2011, but if so why did DConf *this year* have a talk on this issue?!

-- 
Shriramana Sharma ஶ்ரீரமணஶர்மா श्रीरमणशर्मा
June 01, 2013
On 05/31/2013 04:41 PM, Shriramana Sharma wrote:

> On Fri, May 31, 2013 at 8:55 PM, Jonathan M Davis <jmdavisProg@gmx.com> wrote:
>> In D, const ref does not accept rvalues (unlike C++'s const &).
>
> So what is the syntax that accepts rvalues and yet does not make a
> copy of the input object?

I think there has been some resolution on that but it has not been implemented yet. I have not read all of the thread. Can others give a summary of the following thread please?

  http://forum.dlang.org/thread/km3k8v$80p$1@digitalmars.com

> I mean, as Ali says OK profiling is
> preferable to find out where exactly passing by value is more
> efficient than passing by const ref, but I'd like to know anyway what
> is the syntax available for this

That syntax is not available yet. Currently you can take by 'ref const' that does not accept rvalues, or take by value that works for both.

Of course there is also function overloading:

import std.stdio;

struct S
{
    int[100] big;
}

void foo(ref const(S) s)
{
    writeln("lvalue arg passed by ref");
}

void foo(S s)
{
    writeln("either lvalue arg has been copied or rvalue arg has been moved");
}

void main()
{
    auto s = S();

    foo(s);
    foo(S());
}

However, even the lvalue goes to the by-copy overload of foo:

either lvalue arg has been copied or rvalue arg has been moved
either lvalue arg has been copied or rvalue arg has been moved

 Is that by-design? The lvalue s goes to the by-ref overload only if the variable is const to begin with:

    auto s = const(S)();

Now the output is this:

lvalue arg passed by ref
either lvalue arg has been copied or rvalue arg has been moved

Is that how the overload resolution rules work? Have I asked this already? Why don't I remember? :)

Maybe the programmer should not have such large structs anyway. It is always an option to use a slice instead of that fixed-length array.

> I just finished reading this link which Ali gave:
> http://bartoszmilewski.com/2008/11/03/who-ordered-rvalue-references-part-3/
> but perhaps due to my ignorance I don't get 100% what he is tryring to
> say.

That article is about how moving objects is a fundamental operation of D. C++ has three popular basic operations: construction, copy, and assignment. C++11 brings another one: move. Move has been a fundamental struct operation in D for a long time now.

> Is it really relevant for what I am asking, like avoiding a
> copy-constructor in the input of a function which will not modify its
> input, even if I pass by value?

No, not directly relevant but structs object are supposed to be values without identities. The compiler can move them around freely. Maybe that is a better way of looking at the problem.

For example, there is not a concept of a copy constructor. The compiler bit-copies and then provides a chance to make corrections. That is different from C++.

> unfinished language features (scope?)

'scope' is not essential at all, but you are right: There may be other issues down the road.

> I think I may stick with C++ at least for the present project and maybe use
> D for future ones. Advice?

I will let you and others answer that question.

Ali

June 01, 2013
On 05/31/2013 04:45 PM, Shriramana Sharma wrote:

> And again, sorry if I'm being dumb, but is the proposed inout syntax
> intended to fix this problem or some other problem?

Think of 'inout' as a placeholder for one of the following three:

- const
- immutable
- (no const, nor immutable)

inout is deduced at call time and all of the inouts inside a function and even the return type become the qualifier of the argument:

inout(int)[] firstHalf(inout(int)[] a)
{
    return a[0..$/2];
}

void main()
{
    int[] m;
    const(int)[] c;
    immutable(int)[] i;

    assert(is (typeof(firstHalf(m)) == int[]));
    assert(is (typeof(firstHalf(c)) == const(int)[]));
    assert(is (typeof(firstHalf(i)) == immutable(int)[]));
}

That is a very handy feature for exactly situations like the above.

> why did DConf *this year* have a talk on this issue?!

The previous DConf was in 2007. It will be a yearly event from now on.

Ali

June 01, 2013
On Saturday, June 01, 2013 05:11:44 Shriramana Sharma wrote:
> On Fri, May 31, 2013 at 8:55 PM, Jonathan M Davis <jmdavisProg@gmx.com>
wrote:
> > In D, const ref does not accept rvalues (unlike C++'s const &).
> 
> So what is the syntax that accepts rvalues and yet does not make a copy of the input object?

If you have a templated function, you can use auto ref

auto foo(T)(auto ref T var) {..}

or if you don't want to templatize the type but just the function:

auto foo()(auto ref T var) {...}

For non-templated functions, there currently is no solution. You're forced to duplicate the function. Various options are under discussion, and it's likely that auto ref will be used but with slightly different semantics (auto ref on templated functions actually results in two functions - one with ref and one without - and that won't work with non-templated functions). But that hasn't been agreed upon yet. We _will_ have a solution, but it's a hot topic that's still under debate. For various technical reasons, we won't go the C++ route of having const ref accept rvalues (which is usually what people suggest), but we will have a solution relatively soon as there's a fair bit of pressure to resolve the problem.

- Jonathan M Davis
June 01, 2013
On Saturday, June 01, 2013 04:39:07 Shriramana Sharma wrote:
> On Sat, Jun 1, 2013 at 1:13 AM, Jonathan M Davis <jmdavisProg@gmx.com>
wrote:
> > Certainly,
> > for anything that's small enough to fit in a register, it's likely to be
> > faster to pass by value.
> 
> So pardon my ignorance, but a pair which only contains two doubles -- it would fit in a CPU register? How about a bezier class/struct which contains 4 pairs i.e. 8 doubles?

I really don't know. I don't generally deal with anything at the register level. Normally, what you do is you just pass by value unless you know that the struct is huge, and then you just worry about whether passing by value or by reference if profiling makes it clear that passing by value is a performance hit. But it seems to me that in general, worrying about whether something with a few ints or floats in it is going to be able to be passed in a register or not isn't particularly productive unless you've already found it to be a performance problem or know that you're in an environment where it really matters (in which case, you probably know enough about registers to be far better informed about what is and isn't efficient).

> And that would mean that passing by value is faster 'cause it's cheaper to copy the data to a register and have the processor operate on it directly than to copy the pointer (which lies beneath the reference) and have the indirection and *then* copy (?) the data? (I mean I'm not sure how these things work -- even when you are using a pointer/reference, copying from the memory to CPU register is unavoidable right? C++'s const T & only makes it so that copying from memory-to-memory can be avoided, right?

Why would you be copying the data if it was a pointer that was passed? If you pass by ref or by pointer, then only a pointer to the data is copied. Member variables may be copid into registers when operated on, but only the pieces that you operated on would end up being copied into registers, and only then if what you're doing requires a register. There's plenty of stuff that just gets passed around on the stack without any operations being done on them besides copying or moving them. It all depends on what's being done with them.

But it's been too long since I studied assembly for me to be able to go into all of the details with registers and the like.

- Jonathan M Davis
June 01, 2013
On Saturday, June 01, 2013 05:15:22 Shriramana Sharma wrote:
> On Sat, Jun 1, 2013 at 5:11 AM, Shriramana Sharma <samjnaa@gmail.com> wrote:
> > So what is the syntax that accepts rvalues and yet does not make a copy of the input object? I mean, as Ali says OK profiling is preferable to find out where exactly passing by value is more efficient than passing by const ref, but I'd like to know anyway what is the syntax available for this so at least until I get my D legs, I can continue some of my practices from C++ without much detriment.
> 
> And again, sorry if I'm being dumb, but is the proposed inout syntax intended to fix this problem or some other problem? http://d.puremagic.com/issues/show_bug.cgi?id=3748 is marked as resolved fixed from back in 2011, but if so why did DConf *this year* have a talk on this issue?!

inout is completely unrelated. It has to do with having a function which accepts mutable, const, and immutable and returns the same level mutability without having to duplicate your function. You don't want to have to have something like

int[] foo(int[] bar)
{
 ... do something
 return bar[i .. j];
}

const(int)[] foo(const(int)[] bar)
{
 ... do something
 return bar[i .. j];
}


immutable(int)[] foo(immutable(int)[] bar)
{
 ... do something
 return bar[i .. j];
}

Without inout, you're forced to do this kind of code duplication when you want to accept multiple types of mutability and return the same mutability. You could just accept const, but then you'd have to return const rather than the original type which could also have been mutable or immutable.

const(int)[] foo(const(int)[] bar)
{
 ... do something
 return bar[i .. j];
}

inout solves that problem:

inout(int)[] foo(inout(int)[] bar)
{
 ... do something
 return bar[i .. j];
}

You only have to write the function once, and it works with all 3 levels of mutability.

- Jonathan M Davis