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);