Consistency, Templates, Constructors, and D3

F i L witte2008 at gmail.com
Mon Aug 27 15:44:51 PDT 2012


Era Scarecrow wrote:
>  I'm sure in C# that all structs and classes are heap allocated 
> (It takes after C++ very likely) that's the simplest way to do 
> it. You can do that in C++ as well, but other than having to 
> declare it a pointer first. In C++ they made structs 'classes 
> that are public by default' by it's definition I believe. 
> Considering how C++ is set up that makes perfect sense.

C# structs are allocated on the stack when they can be. In 
certain cases (they're class fields, they're boxed, etc..) 
they're heap allocated.


> By looking at newFoo I'd say a class; But if like in C# I'm 
> sure you can't tell the difference (But C++ with the pointer 
> you can).

the 'auto' keyword kind negates the 'Type*' distinction. My point 
here is that you pretty much have to look up the type definition 
(or a tooltip) to understand what you're working with when 
factory functions are involved.


> And for factory functions I'd put them inside the struct/class, 
> unless I had a compelling reason not to.
>
>   class Record {
>     static Record newRecord(string options) {
>       Record rec = new Record();
>       // stuff building the complex record
>       return rec;
>     }
>   }

The result is the same weather they're inside or outside a class, 
because, when used, all the coder sees is the function name to 
know about what it's returning.

In D there is a difference between structs and classes beyond 
what's in C++. The 'new' keyword helps us understand what kind of 
object is being created, and I enjoy that. However, my argument 
is in favor of consistency because right now factory-functions, 
which _are_ used a lot, completely hide that distinction on top 
of being inconsistent with "normal" type construction.


>  And a postblits would end up being...? The extra 'this' makes 
> it look like an obvious typo or a minor headache.
>
>  this this(this){} //postblitz?

I'm sure this case has an easy solution. How about:

     struct Foo {
         this new() { ... } // constructor
         this() { ... } // postblit
     }


>  Only if you start getting creative can it begin to get 
> confusing;

And I have to completely disagree with you here. Memory Pools are 
used everywhere in performance-critical code which needs a 
dynamic array of objects. At least half of all the "allocation" 
in game engines is done through factory functions that recycle 
objects.

And for overload distinction (new vs load), which is an issue 
beyond Memory Pools and effects and even larger codebase. There 
needs to be a consistent way to distinguish (by name) a 
constructor that loads from a file, and one that creates the 
object "manually".


>  If we take your approach and suggestion, which one should the 
> compile assume?
>
>  Something globalSomething;
>
>  class Something {
>    this defaultConstructor();
>    this duplicate(); //or clone
>    this copyGlobalSomething();
>    this constructorWithDefault(int x = 100);
>  }
>
> By signature alone... Which one? They are all legal, they are 
> uniquely named, and they are all equal candidates. Order of 
> functions are irrelevant.

It could work identically to how D functions today. A 'new()' 
constructor would be part of the root Object classes are derived 
of, and structs would have an implicit 'new()' constructor.

This could work in our favor, because instead of 'new' we could 
use 'alloc' (or something like that) while still encouraging 
'new'. Which means structs could provide a parameter-less new() 
constructor:

     class Foo {
         float x;
         // no constructor
     }

     auto f = Foo.alloc();
     assert(f.x == float.nan);

     ---

     struct Point {
         float x, y;
         this new() { x = 0; y = 0; }
         this new(float x, float y) { ... }
     }

     auto a = Point.new();
     auto b = Point.new(1, 2);
     assert(a.x == 0.0f);


More information about the Digitalmars-d mailing list