Jump to page: 1 24  
Page
Thread overview
struct and default constructor
Nov 27, 2011
deadalnix
Nov 27, 2011
deadalnix
Nov 27, 2011
Andrej Mitrovic
Nov 27, 2011
deadalnix
Nov 28, 2011
Steve Teale
Nov 27, 2011
Andrej Mitrovic
Nov 27, 2011
Simen Kjærås
Nov 27, 2011
deadalnix
Oct 10, 2014
dcrepid
Oct 10, 2014
ketmar
Oct 10, 2014
dcrepid
Oct 10, 2014
ketmar
Oct 10, 2014
dcrepid
Oct 10, 2014
ketmar
Oct 11, 2014
Nicolas Sicard
Oct 11, 2014
ketmar
Oct 11, 2014
dcrepid
Oct 10, 2014
Marc Schütz
Oct 11, 2014
Dicebot
Oct 10, 2014
Walter Bright
Oct 10, 2014
Szymon Gatner
Oct 10, 2014
Walter Bright
Oct 10, 2014
ketmar
Oct 10, 2014
Walter Bright
Oct 11, 2014
Simon A
Oct 11, 2014
Walter Bright
Oct 11, 2014
Dicebot
Oct 11, 2014
Walter Bright
Oct 11, 2014
Jonathan M Davis
Oct 11, 2014
dcrepid
Oct 11, 2014
ketmar
Oct 11, 2014
dcrepid
Oct 10, 2014
monarch_dodra
Oct 12, 2014
Nick Treleaven
November 27, 2011
Hi,

I wonder why struct can't have a default constructor. TDPL state that it is required to allow every types to have a constant .init .

That is true, however not suffiscient. A struct can has a void[constant] as a member and this doesn't have a .init . So this limitation does not ensure that the benefit claimed is garanteed.

Additionnaly, if it is the only benefit, this is pretty thin compared to the drawback of not having a default constructor.

We already have @disable this(); for structs. This cause the struct to behave differently and cause the error « initializer required for type xxx » when a variable of type xxx is defined without initialization. This doesn't prevent the struct to get a constant .init and to use it (even if this .init is probably garbage in this case, the whole point of the @disable is to force the user to use a constructor or to copy).

The whole stuff seems very unclear and limitations arbitrary.

Note that a static opCall and a @disabel default constructor doesn't do the trick as opCall can't be used with new to allocate on the heap. This is only a cheap workaround.

Note also that xxx myvar = xxx.init; worls and doesn't trigger postblit. So the @disable this(); is also a structure thatd oesn't garantee anything.

The point of classes and struct beeing different in D is slicing. Default constructor is unrelated to that problem.

Why not allow both @disable this(); and default constructor construct, both triggering the error « initializer required for type xxx » ? This would make much more sense. Postblit should also be triggered on assiagnation with .init to ensure the consistency of the whole construct.
November 27, 2011
In addition, here is a workaround :

// Wonderfull !
@disable this();

// Default constructor workaround.
this(int dummy = 0) { ... }

But that look very dirty and it feels like working against the language.
November 27, 2011
That's not a workaround, that ctor never gets called unless you pass an argument.
November 27, 2011
Wait nevermind, I thought you mean't the ctor *actually runs*. What you meant was disable this() doesn't work with that ctor in place.

On 11/27/11, Andrej Mitrovic <andrej.mitrovich@gmail.com> wrote:
> That's not a workaround, that ctor never gets called unless you pass an argument.
>
November 27, 2011
Le 27/11/2011 21:39, Andrej Mitrovic a écrit :
> That's not a workaround, that ctor never gets called unless you pass
> an argument.

So if you @disable this(); you shouldn't get an error. Actually, you have an implicit constructor, even if it's only to set the variable as equal to .init property of the struct.
November 27, 2011
On Sun, 27 Nov 2011 21:19:38 +0100, deadalnix <deadalnix@gmail.com> wrote:

> In addition, here is a workaround :
>
> // Wonderfull !
> @disable this();
>
> // Default constructor workaround.
> this(int dummy = 0) { ... }
>
> But that look very dirty and it feels like working against the language.

I believe your "workaround" will disappoint you, as it simply does not run.

import std.stdio;

struct A {
    int value;
    @disable this();
    this(int dummy = 0) {
        value = 3;
        writeln("Hello from struct default constructor!"); // Never happens.
    }
}

void main() {
    A a = A();
    writeln( a.value ); // Writes 0
}

More importantly, this shows a bug in DMD - namely that structs with
@disabled default constructors can be created without a call to any
constructor and with no error message. In fact, if one removes the
constructor with dummy arguments, the program still compiles.

http://d.puremagic.com/issues/show_bug.cgi?id=7021
November 27, 2011
Le 27/11/2011 22:24, Simen Kjærås a écrit :
> On Sun, 27 Nov 2011 21:19:38 +0100, deadalnix <deadalnix@gmail.com> wrote:
>
>> In addition, here is a workaround :
>>
>> // Wonderfull !
>> @disable this();
>>
>> // Default constructor workaround.
>> this(int dummy = 0) { ... }
>>
>> But that look very dirty and it feels like working against the language.
>
> I believe your "workaround" will disappoint you, as it simply does not run.
>
> import std.stdio;
>
> struct A {
> int value;
> @disable this();
> this(int dummy = 0) {
> value = 3;
> writeln("Hello from struct default constructor!"); // Never happens.
> }
> }
>
> void main() {
> A a = A();
> writeln( a.value ); // Writes 0
> }
>
> More importantly, this shows a bug in DMD - namely that structs with
> @disabled default constructors can be created without a call to any
> constructor and with no error message. In fact, if one removes the
> constructor with dummy arguments, the program still compiles.
>
> http://d.puremagic.com/issues/show_bug.cgi?id=7021

So that is even worse that what I though. This struct situation is very messy and inconsistent. We should definie what we want for that and have a descent spec.

I just found something new : if you disable this(this), then opAssign should be allowed (it is allowed, according to the website, when implicit cast doesn't exists). The copy don't work with opAssign and disabled postblit . . .
November 28, 2011
On Sun, 27 Nov 2011 21:39:05 +0100, Andrej Mitrovic wrote:

> That's not a workaround, that ctor never gets called unless you pass an argument.

But it lets you pass a Range test.
October 10, 2014
On Sunday, 27 November 2011 at 19:50:24 UTC, deadalnix wrote:
> Hi,
>
> I wonder why struct can't have a default constructor...

I know this is an old thread, but I've run into this same problem recently and search yielded this result.

I myself have tried working around the default-constructor problem with things like

this(bool bInit = true)

- which of course doesn't get invoked with MyStruct(), even with @disable this.

This seems like a language limitation to me.  I have a few templated resource management objects that rely on RAII, but sometimes there's no real use for arguments, especially if a template defines what needs to be created.  But now I'm forced to both disable the default constructor AND to require unnecessary parameters. Why?  Another workaround is to use some object factory mechanism, but that's just extra code to maintain.

Also, apparently doing cleanup in class object destructors is a big no-no as resources that it may need to clean up could potentially already be destroyed, depending on when the GC kicks in and what objects are cleared by it. So no possibility of using objects as resource acquire/release mechanisms.

I assume using scoped with class objects will have a similar problem..
October 10, 2014
On Fri, 10 Oct 2014 01:32:51 +0000
dcrepid via Digitalmars-d <digitalmars-d@puremagic.com> wrote:

> This seems like a language limitation to me.
that is what we have to pay for the rule "type must always has well-defined initial value".

the thing is that struct must have initial value that can be calculated without executing any code. i.e. `T.init`. with default struct constructor we can't have such initial state anymore. this is highly unsafe.

yet compiler ignores constructor with default args when creating struct. i.e. for this:

  struct A {
    @disable this ();
    this (int v=42) { ... }
    ...
  }
  ...
  auto a = A();

compiler will not call this(42), but will generate error. i'm not sure if this must be changed though, 'cause `this (int)` now becames default constructor and we have no well-defined initial value anymore.

> So no possibility of using
> objects as resource acquire/release mechanisms.
> I assume using scoped with class objects will have a similar
> problem..
no, stack-allocated object is GC root, so anything it holds reference to will not be destroyed until stack object is alive. so destructor of stack-allocated object *can* be used for doing cleanup.

but you can use templates to build your "anchor" structs. it's hard to say without concrete code samples.


« First   ‹ Prev
1 2 3 4