www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - How to use structs for RAII?

reply Sean Eskapp <eatingstaples gmail.com> writes:
It was recommended to me to use structs for RAII instead of scope classes,
since scope is being removed (?). However, since default-constructors for
structs can't exist, how does one do this?
Jan 22 2011
next sibling parent reply bearophile <bearophileHUGS lycos.com> writes:
Sean Eskapp:

 It was recommended to me to use structs for RAII instead of scope classes,
 since scope is being removed (?). However, since default-constructors for
 structs can't exist, how does one do this?

Inside the ~this() you may put code, to deallocate resources you have allocated in an explicit constructor (or in some creation method). Is this enough? Bye, bearophile
Jan 22 2011
next sibling parent reply Sean Eskapp <eatingstaples gmail.com> writes:
== Quote from bearophile (bearophileHUGS lycos.com)'s article
 Sean Eskapp:
 It was recommended to me to use structs for RAII instead of scope classes,
 since scope is being removed (?). However, since default-constructors for
 structs can't exist, how does one do this?


 Bye,
 bearophile

By explicit constructor, I assume you mean one with parameters? I guess that's alright.
Jan 22 2011
next sibling parent reply Sean Eskapp <eatingstaples gmail.com> writes:
What's the difference between assert and enforce in D?
Jan 22 2011
parent reply Robert Clipsham <robert octarineparrot.com> writes:
On 23/01/11 00:33, Sean Eskapp wrote:
 What's the difference between assert and enforce in D?

Use assert() for something that must almost be true, regardless of user input, or anything else. enforce() on the other hand is for things which may or may not be true. The source code should clear things up: ---- T enforce(T)(T value, lazy Throwable ex) { if (!value) throw ex(); return value; } ---- So it's essentially just shorthand for throwing an exception. Example: ---- void main(string[] args) { enforce(args.length > 2, "The user needs to pass the correct parameters"); assert(1+1==2, "If this isn't true, the application should terminate"); } ---- -- Robert http://octarineparrot.com/
Jan 22 2011
parent Sean Eskapp <eatingstaples gmail.com> writes:
Ah, that clears it up. Thanks!
Jan 22 2011
prev sibling parent Jacob Carlborg <doob me.com> writes:
On 2011-01-23 01:14, Andrej Mitrovic wrote:
 A workaround:

 import std.stdio;
 import std.exception;

 struct A
 {
      int x;

      this(void* none)
      {
          if (none !is null)
          {
              enforce(0, "Tried to pass a parameter to A's constructor");
          }

          writeln("in constructor");
          // construction from here..
          x = 5;
      }
 }

 void main()
 {
      auto a = A(null);
 }

 I think that would be safe, and closest to a "default" constructor.

A static opCall would be better. See my answer to the original post. -- /Jacob Carlborg
Jan 23 2011
prev sibling next sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
A workaround:

import std.stdio;
import std.exception;

struct A
{
    int x;

    this(void* none)
    {
        if (none !is null)
        {
            enforce(0, "Tried to pass a parameter to A's constructor");
        }

        writeln("in constructor");
        // construction from here..
        x = 5;
    }
}

void main()
{
    auto a = A(null);
}

I think that would be safe, and closest to a "default" constructor.
Jan 22 2011
prev sibling next sibling parent Sean Eskapp <eatingstaples gmail.com> writes:
Actually this becomes rather annoying, since I can't use any closures on the
object. Stupidly, I can still use closures with an object which is deleted at
the
end of the function.
Jan 22 2011
prev sibling next sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
assert also disappears when building in release mode.

On 1/23/11, Robert Clipsham <robert octarineparrot.com> wrote:
 On 23/01/11 00:33, Sean Eskapp wrote:
 What's the difference between assert and enforce in D?

Use assert() for something that must almost be true, regardless of user input, or anything else. enforce() on the other hand is for things which may or may not be true. The source code should clear things up: ---- T enforce(T)(T value, lazy Throwable ex) { if (!value) throw ex(); return value; } ---- So it's essentially just shorthand for throwing an exception. Example: ---- void main(string[] args) { enforce(args.length > 2, "The user needs to pass the correct parameters"); assert(1+1==2, "If this isn't true, the application should terminate"); } ---- -- Robert http://octarineparrot.com/

Jan 22 2011
prev sibling next sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Saturday 22 January 2011 15:09:29 bearophile wrote:
 Sean Eskapp:
 It was recommended to me to use structs for RAII instead of scope
 classes, since scope is being removed (?). However, since
 default-constructors for structs can't exist, how does one do this?

Inside the ~this() you may put code, to deallocate resources you have allocated in an explicit constructor (or in some creation method). Is this enough?

The typical thing to do when you want a default constructor for a struct is to use a static opCall(). Then, for struct S, you'd do auto s = S(); If you did S s(), it still wouldn't work, so you might want to add an assertion in the destructor which verifes that the struct wasn't constructor with S.init, in which case what the destructor would be doing would likely be wrong. Personally, I _always_ declare struct variables in this form auto s = S(); and never as S s(); It avoids most of the problem with a struct's init value. But you can still get structs initialized to their init when they're in arrays and the like (which is a good part of the reason that init exists in the first place). - Jonathan M Davis
Jan 22 2011
prev sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
Ah, I keep forgetting about opCall. Nice tips there.
Jan 23 2011
prev sibling parent Jacob Carlborg <doob me.com> writes:
On 2011-01-23 00:03, Sean Eskapp wrote:
 It was recommended to me to use structs for RAII instead of scope classes,
 since scope is being removed (?). However, since default-constructors for
 structs can't exist, how does one do this?

You can use a static opCall, like this: struct Foo { static Foo opCall () { Foo foo; // initialize foo return foo; } } auto foo = Foo(); -- /Jacob Carlborg
Jan 23 2011