www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - disable this for structs

reply "Steve Teale" <steve.teale britseyeview.com> writes:
Could someone please explain what you would use this for to an 
old man rooted in C++, but who loves D.

Where does it fit in relative to 42?

;=(

Steve
Feb 27 2014
next sibling parent reply "Namespace" <rswhite4 googlemail.com> writes:
On Thursday, 27 February 2014 at 18:10:38 UTC, Steve Teale wrote:
 Could someone please explain what you would use this for to an 
 old man rooted in C++, but who loves D.

 Where does it fit in relative to 42?

 ;=(

 Steve
It's for explicit initialization: struct Foo { } Foo f; // no problem struct Bar { disable this(); } Bar b; // error
Feb 27 2014
parent reply "Steve Teale" <steve.teale britseyeview.com> writes:
On Thursday, 27 February 2014 at 18:13:43 UTC, Namespace wrote:
 On Thursday, 27 February 2014 at 18:10:38 UTC, Steve Teale 
 wrote:
 Could someone please explain what you would use this for to an 
 old man rooted in C++, but who loves D.

 Where does it fit in relative to 42?

 ;=(

 Steve
It's for explicit initialization: struct Foo { } Foo f; // no problem struct Bar { disable this(); } Bar b; // error
So it is just a reminder that you need to initialize Bar in some specific way?
Feb 27 2014
next sibling parent "John Colvin" <john.loughran.colvin gmail.com> writes:
On Thursday, 27 February 2014 at 18:26:10 UTC, Steve Teale wrote:
 On Thursday, 27 February 2014 at 18:13:43 UTC, Namespace wrote:
 On Thursday, 27 February 2014 at 18:10:38 UTC, Steve Teale 
 wrote:
 Could someone please explain what you would use this for to 
 an old man rooted in C++, but who loves D.

 Where does it fit in relative to 42?

 ;=(

 Steve
It's for explicit initialization: struct Foo { } Foo f; // no problem struct Bar { disable this(); } Bar b; // error
So it is just a reminder that you need to initialize Bar in some specific way?
pretty much, yes. More precisely, it disables the implicit no-op default constructor, forcing the user to use a different one.
Feb 27 2014
prev sibling parent "Namespace" <rswhite4 googlemail.com> writes:
On Thursday, 27 February 2014 at 18:26:10 UTC, Steve Teale wrote:
 On Thursday, 27 February 2014 at 18:13:43 UTC, Namespace wrote:
 On Thursday, 27 February 2014 at 18:10:38 UTC, Steve Teale 
 wrote:
 Could someone please explain what you would use this for to 
 an old man rooted in C++, but who loves D.

 Where does it fit in relative to 42?

 ;=(

 Steve
It's for explicit initialization: struct Foo { } Foo f; // no problem struct Bar { disable this(); } Bar b; // error
So it is just a reminder that you need to initialize Bar in some specific way?
aye
Feb 27 2014
prev sibling next sibling parent "Adam D. Ruppe" <destructionator gmail.com> writes:
Basically, disabling the default constructor just forces the user 
to think about what they want there to initialize it, which also 
gives you a chance to check their values or funnel them toward a 
particular constructor/factory method.

They can still choose to explicitly leave it unitialized with 
=void, or call a constructor with some value.

Just when you write

Foo f;

and the compiler complains that default constructor is disabled, 
now you have to actually think about what to do next. If you 
consult the docs, it might say "use Foo.create() instead" and now 
you know. Or you might give it some value that makes sense.
Feb 27 2014
prev sibling parent reply Mike Parker <aldacron gmail.com> writes:
On 2/28/2014 3:10 AM, Steve Teale wrote:
 Could someone please explain what you would use this for to an old man
 rooted in C++, but who loves D.

 Where does it fit in relative to 42?

 ;=(

 Steve
I use it for namespaces. struct Foo { disable this(); disable this( this ); private static { // members } public static { // methods } } Ideally, I'd love for the compiler to pick up on this idiom and not generate any typeinfo in this situation.
Feb 27 2014
next sibling parent "Namespace" <rswhite4 googlemail.com> writes:
On Friday, 28 February 2014 at 01:16:41 UTC, Mike Parker wrote:
 On 2/28/2014 3:10 AM, Steve Teale wrote:
 Could someone please explain what you would use this for to an 
 old man
 rooted in C++, but who loves D.

 Where does it fit in relative to 42?

 ;=(

 Steve
I use it for namespaces. struct Foo { disable this(); disable this( this ); private static { // members } public static { // methods } } Ideally, I'd love for the compiler to pick up on this idiom and not generate any typeinfo in this situation.
For such namespaces I use final abstract classes: final abstract class Foo { static: // members }
Feb 27 2014
prev sibling next sibling parent "bearophile" <bearophileHUGS lycos.com> writes:
Mike Parker:

 Ideally, I'd love for the compiler to pick up on this idiom and 
 not generate any typeinfo in this situation.
Is this in Bugzilla somewhere? If it's a good idea then it could and should go in Bugzilla. Bye, bearophile
Feb 27 2014
prev sibling parent reply "Dicebot" <public dicebot.lv> writes:
On Friday, 28 February 2014 at 01:16:41 UTC, Mike Parker wrote:
 Ideally, I'd love for the compiler to pick up on this idiom and 
 not generate any typeinfo in this situation.
Ideally one should use modules as namespaces :P
Feb 28 2014
next sibling parent reply "Remo" <remo4d gmail.com> writes:
On Friday, 28 February 2014 at 11:59:40 UTC, Dicebot wrote:
 On Friday, 28 February 2014 at 01:16:41 UTC, Mike Parker wrote:
 Ideally, I'd love for the compiler to pick up on this idiom 
 and not generate any typeinfo in this situation.
Ideally one should use modules as namespaces :P
Ideally D should have build in namespaces. Using class to mimic namespace, but then all the functions are virtual per default ?
Feb 28 2014
next sibling parent "Tobias Pankrath" <tobias pankrath.net> writes:
On Friday, 28 February 2014 at 12:52:38 UTC, Remo wrote:
 On Friday, 28 February 2014 at 11:59:40 UTC, Dicebot wrote:
 On Friday, 28 February 2014 at 01:16:41 UTC, Mike Parker wrote:
 Ideally, I'd love for the compiler to pick up on this idiom 
 and not generate any typeinfo in this situation.
Ideally one should use modules as namespaces :P
Ideally D should have build in namespaces.
Why? C like tag namespaces are awful and do C++ like namespaces offer any benefit over modules? Keep in mind that we have no Koenig lookup.
Feb 28 2014
prev sibling parent reply "Dicebot" <public dicebot.lv> writes:
On Friday, 28 February 2014 at 12:52:38 UTC, Remo wrote:
 On Friday, 28 February 2014 at 11:59:40 UTC, Dicebot wrote:
 On Friday, 28 February 2014 at 01:16:41 UTC, Mike Parker wrote:
 Ideally, I'd love for the compiler to pick up on this idiom 
 and not generate any typeinfo in this situation.
Ideally one should use modules as namespaces :P
Ideally D should have build in namespaces. Using class to mimic namespace, but then all the functions are virtual per default ?
No. By design namespace is a module. You don't use classes for namespaces, you create more modules. One may not like it but it is how D module system was created and it was intentional.
Feb 28 2014
parent reply "Remo" <remo4d gmail.com> writes:
On Friday, 28 February 2014 at 13:23:51 UTC, Dicebot wrote:
 On Friday, 28 February 2014 at 12:52:38 UTC, Remo wrote:
 On Friday, 28 February 2014 at 11:59:40 UTC, Dicebot wrote:
 On Friday, 28 February 2014 at 01:16:41 UTC, Mike Parker 
 wrote:
 Ideally, I'd love for the compiler to pick up on this idiom 
 and not generate any typeinfo in this situation.
Ideally one should use modules as namespaces :P
Ideally D should have build in namespaces. Using class to mimic namespace, but then all the functions are virtual per default ?
No. By design namespace is a module. You don't use classes for namespaces, you create more modules. One may not like it but it is how D module system was created and it was intentional.
Right now I do not really miss namespacec in D. I like modules in D. What I hate already are problems with structs and ctors. Most time while porting C++ code to D I spend a lot of time to resolve all the problems that happens because of struct ctors. If I forget to do this then it still compiles but does not work at all...
Feb 28 2014
parent "Dicebot" <public dicebot.lv> writes:
On Friday, 28 February 2014 at 13:32:13 UTC, Remo wrote:
 What I hate already are problems with structs and ctors.
 Most time while porting C++ code to D I spend a lot of time to 
 resolve all the problems that happens because of struct ctors.
 If I forget to do this then it still compiles but does not work 
 at all...
It is a long-standing bug and I am sorry for that. See http://forum.dlang.org/post/wziedbjjmxvabubvankk forum.dlang.org
Feb 28 2014
prev sibling parent reply Mike Parker <aldacron gmail.com> writes:
On 2/28/2014 8:59 PM, Dicebot wrote:
 On Friday, 28 February 2014 at 01:16:41 UTC, Mike Parker wrote:
 Ideally, I'd love for the compiler to pick up on this idiom and not
 generate any typeinfo in this situation.
Ideally one should use modules as namespaces :P
I don't buy that. That works fine to resolve conflicts, but it doesn't work for fine-grained namespace management. And when using named imports, that means everything in the module then belongs to that namespace, which isn't at all what I want. Besides which, using either fully-qualified names or named imports puts the impetus on the caller. If I design my modules around namespaces with the understanding that the caller will type foo.bar.myfunc all the time, there are bound to be conflicts when they forget to do it. On the other hand, by wrapping my namespaced stuff in structs or classes, I can have multiple namespaces per module, some things completely outside the namespace, and the user gets a compiler error if they don't use it. To me, that's much, much neater.
Feb 28 2014
parent reply "Dicebot" <public dicebot.lv> writes:
On Friday, 28 February 2014 at 12:59:32 UTC, Mike Parker wrote:
 Ideally one should use modules as namespaces :P
I don't buy that. That works fine to resolve conflicts, but it doesn't work for fine-grained namespace management. And when using named imports, that means everything in the module then belongs to that namespace, which isn't at all what I want. Besides which, using either fully-qualified names or named imports puts the impetus on the caller. If I design my modules around namespaces with the understanding that the caller will type foo.bar.myfunc all the time, there are bound to be conflicts when they forget to do it.
D design is based on module as smallest composition unit. If you find yourself in situation where you want to have two namespaces in a single module, you should split it into two modules. Putting impetus on caller (named imports) is good here and huge advantage over C++ way in my opinion. It gives more control over application naming scheme.
 On the other hand, by wrapping my namespaced stuff in structs 
 or classes, I can have multiple namespaces per module, some 
 things completely outside the namespace, and the user gets a 
 compiler error if they don't use it. To me, that's much, much 
 neater.
It simply does not fit with D type system, most importantly with accessiblity attributes. I'd hate to encounter all that you mention as "benefits" in some D library I am forced to use.
Feb 28 2014
parent reply Mike Parker <aldacron gmail.com> writes:
On 2/28/2014 10:21 PM, Dicebot wrote:
 D design is based on module as smallest composition unit. If you find
 yourself in situation where you want to have two namespaces in a single
 module, you should split it into two modules.
Consider this. enum Foo {...} interface Bar {} struct BarManager { public static { void initialize(); void terminate(); ... more stuff } } This is my use-case. I don't want my users to have to refer to Foo or Bar with any sort of prefix except to avoid name-clashes. However, I want to logically group the functions to manage Bars under a single grouping. I don't need or want a Singleton for it. I could use free functions, but I use the initialize/terminate idiom a lot. As a user of my own library, it would be horribly annoying to have to fully qualify each call. Plus, now and again I have multiple "namespace structs" in a single module. If I see them as all being closely related, why should I split them off into different modules?
 Putting impetus on caller (named imports) is good here and huge
 advantage over C++ way in my opinion. It gives more control over
 application naming scheme.

 On the other hand, by wrapping my namespaced stuff in structs or
 classes, I can have multiple namespaces per module, some things
 completely outside the namespace, and the user gets a compiler error
 if they don't use it. To me, that's much, much neater.
It simply does not fit with D type system, most importantly with accessiblity attributes. I'd hate to encounter all that you mention as "benefits" in some D library I am forced to use.
One of the most annoying things for me in C++ is to see something like some::ridiculously::long::namespace, that I then have to use on each type declared in that namespace. That makes me add using statements to the top of each module, which defeats the purpose in the first place. I would find it equally annoying in D if every module I imported required me to use a fully-qualified module name. Luckily, that isn't the case. We only need to do it do avoid conflicts. My purpose for using namespaces in this way is twofold: to indicate that those particular functions serve a collective purpose, and to make give more meaning to the user code. I don't need to worry about naming conflicts, thanks to the module system, but I don't see the module as the smallest unit of organization.
Feb 28 2014
parent reply "Dicebot" <public dicebot.lv> writes:
On Friday, 28 February 2014 at 13:42:21 UTC, Mike Parker wrote:
 Consider this.

 enum Foo {...}

 interface Bar {}

 struct BarManager {
    public static {
       void initialize();
       void terminate();
       ... more stuff
    }
 }

 This is my use-case. I don't want my users to have to refer to 
 Foo or Bar with any sort of prefix except to avoid 
 name-clashes. However, I want to logically group the functions 
 to manage Bars under a single grouping. I don't need or want a 
 Singleton for it. I could use free functions, but I use the 
 initialize/terminate idiom a lot. As a user of my own library, 
 it would be horribly annoying to have to fully qualify each 
 call. Plus, now and again I have multiple "namespace structs" 
 in a single module. If I see them as all being closely related, 
 why should I split them off into different modules?
I'd write it this way: === something/bar.d === interface Bar {} === something/barmanager.d === import something.bar; // possibly public import void initialize(); void terminate(); === app.d === import something.bar; import barmanager = something.barmanager; // refer to Bar directly and to init function via barmanager.initialize() ========= Or, even better, turn bar into package and have something.bar.manager with same usage pattern.
Feb 28 2014
parent reply Mike Parker <aldacron gmail.com> writes:
On 2/28/2014 11:37 PM, Dicebot wrote:

 I'd write it this way:

 === something/bar.d ===

 interface Bar {}

 === something/barmanager.d ===

 import something.bar; // possibly public import

 void initialize();
 void terminate();

 === app.d ===

 import something.bar;
 import barmanager = something.barmanager;

 // refer to Bar directly and to init function via barmanager.initialize()
 =========

 Or, even better, turn bar into package and have something.bar.manager
 with same usage pattern.
And as a user of your library, I'm going to be extremely annoyed that I have to keep remembering to declare named imports to disambiguate all the intialize/terminate functions in all the modules that have them. If you're going to design your library that way, you should do it for me :) I see modules, loosely, as a way to group immediate family and packages as a way to group extended family. To me, Bar and BarManager are closely related, so they belong in the same module. It also makes long-term maintenance simpler, since everything related to Bar is in one place. And then there's D's module-scope access to private methods/members, which at some level encourages this approach (and which I make good use of). If I were to break all of my modules up as you have in this example, it unnecessarily inflates the number of modules, increases the maintenance cost somewhat, and takes away my module access to private. Anyway, I have a project I'm working on right now that I'll be putting up on github within a few weeks that serves as a more complete example. One of the great things about D is that it has enough room for both approaches.
Feb 28 2014
parent reply "Dicebot" <public dicebot.lv> writes:
One feature I miss is "partial static import" - one that 
essentially automates `import modname = packname.modname`, 
allowing to qualify by module name only. That could have removed 
some repeating boilerplate from my code.
Feb 28 2014
parent "Steve Teale" <steve.teale britseyeview.com> writes:
On Friday, 28 February 2014 at 16:02:26 UTC, Dicebot wrote:

...

Mmm, simple question, complicated answer. But the first one was 
enough for me at this point.
Feb 28 2014