www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - eliminate new operator paraphernalia

reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Currently new is baroque to the extreme. Should we eliminate the 
class-specific allocators in favor of a simple scheme for placement new? 
All that's really needed is to construct an object of a given type at a 
given address. All of the syntactic mess around it is unnecessary.

I think class-specific new and delete are not a useful feature.

Second, the whole new anonymous class thing is for Java's sake. Do you 
think we need to keep all that?

I suggest the following syntaxes for a type T, an integral length, an 
initializerlist a la "e1, e2, e3, ..." that could be empty, and an addr 
convertible to void*:

new T[length]
new T(initializerlist)
new(addr) T[length]
new(addr) T(initializerlist)

and call it a day.

What do you think?


Andrei
Feb 14 2010
next sibling parent bearophile <bearophileHUGS lycos.com> writes:
Andrei Alexandrescu:
 What do you think?
Can the "new" keyword be removed from D2 and replaced by some class method "new"? :-) Bye, bearophile
Feb 14 2010
prev sibling next sibling parent reply Michel Fortin <michel.fortin michelf.com> writes:
On 2010-02-14 13:17:44 -0500, Andrei Alexandrescu 
<SeeWebsiteForEmail erdani.org> said:

 Currently new is baroque to the extreme. Should we eliminate the 
 class-specific allocators in favor of a simple scheme for placement 
 new? All that's really needed is to construct an object of a given type 
 at a given address. All of the syntactic mess around it is unnecessary.
 
 I think class-specific new and delete are not a useful feature.
 
 Second, the whole new anonymous class thing is for Java's sake. Do you 
 think we need to keep all that?
 
 I suggest the following syntaxes for a type T, an integral length, an 
 initializerlist a la "e1, e2, e3, ..." that could be empty, and an addr 
 convertible to void*:
 
 new T[length]
 new T(initializerlist)
 new(addr) T[length]
 new(addr) T(initializerlist)
 
 and call it a day.
Hum, what's the syntax for placement delete? While I welcome a real placement-new syntax, I'm not sure adding it justifies any of the other changes you're proposing. Placement-new can be see as just another allocator taking a pointer as an argument and returning that same pointer as the address to use for whatever you're initializing. So why remove custom allocators? Those can be useful to catch all allocations of a specific class in an existing code base and improve it for some specific needs without having to change code everywhere. I'd rather see that better generalized (we talked about making 'new' a template earlier). Also, why remove anonymous classes? They're just a shortcut syntax for: void func() { class Anonymous { ... } auto a = new Anonymous; ... } I don't really see what's the problem in allowing this: void func() { auto a = new class { ... } ... } -- Michel Fortin michel.fortin michelf.com http://michelf.com/
Feb 14 2010
next sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Michel Fortin wrote:
 On 2010-02-14 13:17:44 -0500, Andrei Alexandrescu 
 <SeeWebsiteForEmail erdani.org> said:
 
 Currently new is baroque to the extreme. Should we eliminate the 
 class-specific allocators in favor of a simple scheme for placement 
 new? All that's really needed is to construct an object of a given 
 type at a given address. All of the syntactic mess around it is 
 unnecessary.

 I think class-specific new and delete are not a useful feature.

 Second, the whole new anonymous class thing is for Java's sake. Do you 
 think we need to keep all that?

 I suggest the following syntaxes for a type T, an integral length, an 
 initializerlist a la "e1, e2, e3, ..." that could be empty, and an 
 addr convertible to void*:

 new T[length]
 new T(initializerlist)
 new(addr) T[length]
 new(addr) T(initializerlist)

 and call it a day.
Hum, what's the syntax for placement delete?
There is no need for placement delete. There will be a function clear() in object.d that only calls the destructor. (That is needed regardless.) You can carry deallocation with your own API functions.
 While I welcome a real placement-new syntax, I'm not sure adding it 
 justifies any of the other changes you're proposing. Placement-new can 
 be see as just another allocator taking a pointer as an argument and 
 returning that same pointer as the address to use for whatever you're 
 initializing.
Creating an object at a given address is really everything you need from the language to do whatever you want.
 So why remove custom allocators? Those can be useful to catch all 
 allocations of a specific class in an existing code base and improve it 
 for some specific needs without having to change code everywhere. I'd 
 rather see that better generalized (we talked about making 'new' a 
 template earlier).
There are many problems with custom allocators. They hook the syntax and do something that's unbecoming. new T must place T on the garbage-collected heap, period. That gives the guarantee that the object has infinite lifetime and therefore dependable behavior. If the same syntax can be used to implement various other semantics, you can't count on anything in generic code.
 Also, why remove anonymous classes?
Walter thinks we need to keep them. Andrei
Feb 14 2010
next sibling parent reply "Nick Sabalausky" <a a.a> writes:
"Andrei Alexandrescu" <SeeWebsiteForEmail erdani.org> wrote in message 
news:hl9n50$2f9v$1 digitalmars.com...
 There are many problems with custom allocators. They hook the syntax and 
 do something that's unbecoming. new T must place T on the 
 garbage-collected heap, period. That gives the guarantee that the object 
 has infinite lifetime and therefore dependable behavior. If the same 
 syntax can be used to implement various other semantics, you can't count 
 on anything in generic code.
Sounds to me like the exact same argument for eliminating operator overloading: "If we allow it, then someone could hijack '+' to do something unbecoming and then you can't count on anything in generic code". Generic code (at least in D) naturally comes with a risk of duckiness. The whole point of custom allocators is to allow something to get the same result (get a new instance) through a different implementation. And as for the infinite lifetime guarantee: I don't think I see any risk of a custom-allocated object getting yanked out from under generic code unless you did something *really* bizarre and obviouly pointless like lauch a thread that randomly marks elements in an object pool as unused.
Feb 14 2010
next sibling parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Nick Sabalausky wrote:
 "Andrei Alexandrescu" <SeeWebsiteForEmail erdani.org> wrote in message 
 news:hl9n50$2f9v$1 digitalmars.com...
 There are many problems with custom allocators. They hook the syntax and 
 do something that's unbecoming. new T must place T on the 
 garbage-collected heap, period. That gives the guarantee that the object 
 has infinite lifetime and therefore dependable behavior. If the same 
 syntax can be used to implement various other semantics, you can't count 
 on anything in generic code.
Sounds to me like the exact same argument for eliminating operator overloading: "If we allow it, then someone could hijack '+' to do something unbecoming and then you can't count on anything in generic code". Generic code (at least in D) naturally comes with a risk of duckiness.
It's not the same argument, but I can't afford the time to debate that.
 The whole point of custom allocators is to allow something to get the same 
 result (get a new instance) through a different implementation.  And as for
 the infinite lifetime guarantee: I don't think I see any risk of a 
 custom-allocated object getting yanked out from under generic code unless 
 you did something *really* bizarre and obviouly pointless like lauch a 
 thread that randomly marks elements in an object pool as unused. 
My point is that custom new is not transparent at all. One typical example of class-specific new and delete is using malloc as a backend. So then you have some types for which you need to pair new and delete, and some for which you don't. Not good. All that's needed is the ability to create an object at a given address, and the ability to destroy a given object. This is what the language must provide. All the rest can and should be built via regular facilities. Andrei
Feb 14 2010
prev sibling parent dsimcha <dsimcha yahoo.com> writes:
== Quote from Nick Sabalausky (a a.a)'s article
 And as for
 the infinite lifetime guarantee: I don't think I see any risk of a
 custom-allocated object getting yanked out from under generic code unless
 you did something *really* bizarre and obviouly pointless like lauch a
 thread that randomly marks elements in an object pool as unused.
...or allocated your object using a LIFO stack allocator of some kind.
Feb 14 2010
prev sibling parent reply Michel Fortin <michel.fortin michelf.com> writes:
On 2010-02-14 15:41:30 -0500, Andrei Alexandrescu 
<SeeWebsiteForEmail erdani.org> said:

 Michel Fortin wrote:
 
 Hum, what's the syntax for placement delete?
There is no need for placement delete. There will be a function clear() in object.d that only calls the destructor. (That is needed regardless.) You can carry deallocation with your own API functions.
What's the point in wasting a function name only to call the destructor? Why not just allow "object.~this()"? Also, if you really want to put an object back in it's initial state, you could call both the destructor and the constructor. Anything else is going to break the object's invariant. I think it's best to leave breaking the object's invariants to a special syntax, hence "object.~this()".
 So why remove custom allocators? Those can be useful to catch all 
 allocations of a specific class in an existing code base and improve it 
 for some specific needs without having to change code everywhere. I'd 
 rather see that better generalized (we talked about making 'new' a 
 template earlier).
There are many problems with custom allocators. They hook the syntax and do something that's unbecoming. new T must place T on the garbage-collected heap, period. That gives the guarantee that the object has infinite lifetime and therefore dependable behavior. If the same syntax can be used to implement various other semantics, you can't count on anything in generic code.
Well, I agree that new should have dependable semantics. I disagree about it being always from a GC-allocated block. There are other ways to create infinite lifetime behaviour, like a smart pointer. Of course you can't do that with 'new' as it stands today because you can't make it return something else than a crude pointer. That's what need to be fixed I think. You could say that having placement-new fixes that problem, and in a way it does because it allows you to create what I've described as a separate function. Except you have to use a different syntax to create the object which makes things less transparent (especially with generic code). Also, having placement-new and regular-new share the almost same syntax isn't a good way to say that 'new' has dependable semantics. I think there is a better syntax for calling the constructor: "object.this()".
 Also, why remove anonymous classes?
Walter thinks we need to keep them.
Is that your reason for wanting them removed? :-) -- Michel Fortin michel.fortin michelf.com http://michelf.com/
Feb 14 2010
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Michel Fortin wrote:
 On 2010-02-14 15:41:30 -0500, Andrei Alexandrescu 
 <SeeWebsiteForEmail erdani.org> said:
 
 Michel Fortin wrote:
 Hum, what's the syntax for placement delete?
There is no need for placement delete. There will be a function clear() in object.d that only calls the destructor. (That is needed regardless.) You can carry deallocation with your own API functions.
What's the point in wasting a function name only to call the destructor? Why not just allow "object.~this()"?
You might want to clear an int etc. for which it's unclear whether the above should work.
 Also, if you really want to put an object back in it's initial state, 
 you could call both the destructor and the constructor. Anything else is 
 going to break the object's invariant. I think it's best to leave 
 breaking the object's invariants to a special syntax, hence 
 "object.~this()".
Yah, clear destroys and then fills with .init. Andrei
Feb 14 2010
next sibling parent Michel Fortin <michel.fortin michelf.com> writes:
On 2010-02-14 17:21:51 -0500, Andrei Alexandrescu 
<SeeWebsiteForEmail erdani.org> said:

 Michel Fortin wrote:
 On 2010-02-14 15:41:30 -0500, Andrei Alexandrescu 
 <SeeWebsiteForEmail erdani.org> said:
 
 Michel Fortin wrote:
 
 Hum, what's the syntax for placement delete?
There is no need for placement delete. There will be a function clear() in object.d that only calls the destructor. (That is needed regardless.) You can carry deallocation with your own API functions.
What's the point in wasting a function name only to call the destructor? Why not just allow "object.~this()"?
You might want to clear an int etc. for which it's unclear whether the above should work.
 Also, if you really want to put an object back in it's initial state, 
 you could call both the destructor and the constructor. Anything else 
 is going to break the object's invariant. I think it's best to leave 
 breaking the object's invariants to a special syntax, hence 
 "object.~this()".
Yah, clear destroys and then fills with .init.
...and call the default constructor for classes (and is not callable if there is no default constructor). If you don't call a constructor for a class, invariants can't hold. Ok. That's fine for clear() then, but it's not the same thing as just calling the destructor. There should be a way to just call the destructor prior deallocation. -- Michel Fortin michel.fortin michelf.com http://michelf.com/
Feb 14 2010
prev sibling next sibling parent Jonathan M Davis <jmdavisProg gmail.com> writes:
Andrei Alexandrescu wrote:

 Also, if you really want to put an object back in it's initial state,
 you could call both the destructor and the constructor. Anything else is
 going to break the object's invariant. I think it's best to leave
 breaking the object's invariants to a special syntax, hence
 "object.~this()".
Yah, clear destroys and then fills with .init. Andrei
How about reinit()?. clear() seems like a name which people would definitely want to use in their own code. The STL uses it for its containers, and you'd then have to come up with a new name for that functionality in any container classes in D. A name which is less likely to be sought after by programmers for their own classes would be better. reinit() is just what comes to mind for me, but I think that it would be a shame to lose clear() to Object. - Jonathan M Davis
Feb 14 2010
prev sibling parent reply grauzone <none example.net> writes:
Andrei Alexandrescu wrote:
 Michel Fortin wrote:
 On 2010-02-14 15:41:30 -0500, Andrei Alexandrescu 
 <SeeWebsiteForEmail erdani.org> said:

 Michel Fortin wrote:
 Hum, what's the syntax for placement delete?
There is no need for placement delete. There will be a function clear() in object.d that only calls the destructor. (That is needed regardless.) You can carry deallocation with your own API functions.
What's the point in wasting a function name only to call the destructor? Why not just allow "object.~this()"?
You might want to clear an int etc. for which it's unclear whether the above should work.
 Also, if you really want to put an object back in it's initial state, 
 you could call both the destructor and the constructor. Anything else 
 is going to break the object's invariant. I think it's best to leave 
 breaking the object's invariants to a special syntax, hence 
 "object.~this()".
Yah, clear destroys and then fills with .init.
How is filling with .init not a waste of time? Now I'm not really sure, but I'm going to guess... you think it's safer? I don't think "reusing" objects is safe memory management. OK, you probably could still sandbox such a program, and there will never be segfaults (except null pointer accesses). But the user could still have references to "dead" objects. Or even worse, "false" objects, that have been reinitialized even though some other parts of the program needed the old object. There, you have the same mess as with traditional manual memory allocation. As a D user, I'm kindly asking for actually safe memory management primitives, that are more efficient than the old GC. By the way, what does "paraphernalia" mean?
 Andrei
Feb 15 2010
next sibling parent "Simen kjaeraas" <simen.kjaras gmail.com> writes:
grauzone <none example.net> wrote:
 what does "paraphernalia" mean?
http://dictionary.reference.com/browse/paraphernalia : 1. (sometimes used with a singular verb) equipment, apparatus, or furnishing used in or necessary for a particular activity: a skier's paraphernalia. 2. (used with a plural verb) personal belongings. 3. (used with a singular verb) Law. the personal articles, apart from dower, reserved by law to a married woman. -- Simen
Feb 15 2010
prev sibling parent =?ISO-8859-1?Q?Pelle_M=E5nsson?= <pelle.mansson gmail.com> writes:
On 02/15/2010 01:27 PM, grauzone wrote:
 How is filling with .init not a waste of time?
It needs to fill with .init and run the default constructor (if any). Contracts, and all that.
Feb 15 2010
prev sibling parent Justin Johansson <no spam.com> writes:
Michel Fortin wrote:
 Also, why remove anonymous classes?
Me thinks that whoever suggested that anonymous classes be removed is best to remain anonymous. :-) Justin Johansson
Feb 14 2010
prev sibling next sibling parent reply "Nick Sabalausky" <a a.a> writes:
"Andrei Alexandrescu" <SeeWebsiteForEmail erdani.org> wrote in message 
news:hl9end$1u8k$1 digitalmars.com...
 Second, the whole new anonymous class thing is for Java's sake. Do you 
 think we need to keep all that?
It doesn't bother me having it, but I can't say I can imagine ever having a use for it outside a fully dynamic scripting language (or maybe Java, but well, Java tools and features tend to be useful primarily as workarounds for Java being it's usual Javay self).
 new T[length]
 new T(initializerlist)
Isn't that exactly what we already have?
 new(addr) T[length]
 new(addr) T(initializerlist)
I'm not sure I see the point of that. Can't you just call the ctor directly?
Feb 14 2010
parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Nick Sabalausky wrote:
 "Andrei Alexandrescu" <SeeWebsiteForEmail erdani.org> wrote in message 
 news:hl9end$1u8k$1 digitalmars.com...
 Second, the whole new anonymous class thing is for Java's sake. Do you 
 think we need to keep all that?
It doesn't bother me having it, but I can't say I can imagine ever having a use for it outside a fully dynamic scripting language (or maybe Java, but well, Java tools and features tend to be useful primarily as workarounds for Java being it's usual Javay self).
 new T[length]
 new T(initializerlist)
Isn't that exactly what we already have?
 new(addr) T[length]
 new(addr) T(initializerlist)
I'm not sure I see the point of that. Can't you just call the ctor directly?
You can't. I mean there is a __ctor thing but user code shouldn't depend on that. Andrei
Feb 14 2010
prev sibling next sibling parent reply Kasumi Hanazuki <k.hanazuki gmail.com> writes:
 I suggest the following syntaxes for a type T, an integral length, an
 initializerlist a la "e1, e2, e3, ..." that could be empty, and an addr
 convertible to void*:

 new T[length]
 new T(initializerlist)
This may be a bit off-topic, but now is the chance to think about the array-new'ing syntax... Currently, D has two syntaxes to allocate a dynamic array (type of T[]), - new int[n]; // n can be a non-constant - new int[](n); and no way to allocate a static array (type of T[N]) dynamically. - new int[3]; // this is not an int[3] but a int[] - alias int[3] int3; new int3; // this is not allowed! I think it is inconsistent in following points: - {new int[1][2][3]} allocates an int[1][2][] of length 3 (only the last parameter has the different meaning). - {new int[3]} and {new int3} behave differently as shown above. So I suggest that - {new T[N]} would accept only a compile-time constant as N and allocate a T[N] as if T[N] were a struct type. - {new T[](n)} would allocate a T[] of length n as if T[] were a class type and had a constructor taking one size_t parameter (same as current implementation). With this semantics, {new int[2][3]} shall allocate an int[2][3], {new int[2][](3)} an int[2][] of length 3, {new int[][](2, 3)} an int[][] of length 3 having three int[] of length 2 as its elements.
Feb 14 2010
parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Kasumi Hanazuki wrote:
 I suggest the following syntaxes for a type T, an integral length, an
 initializerlist a la "e1, e2, e3, ..." that could be empty, and an addr
 convertible to void*:

 new T[length]
 new T(initializerlist)
This may be a bit off-topic, but now is the chance to think about the array-new'ing syntax... Currently, D has two syntaxes to allocate a dynamic array (type of T[]), - new int[n]; // n can be a non-constant - new int[](n); and no way to allocate a static array (type of T[N]) dynamically. - new int[3]; // this is not an int[3] but a int[] - alias int[3] int3; new int3; // this is not allowed! I think it is inconsistent in following points: - {new int[1][2][3]} allocates an int[1][2][] of length 3 (only the last parameter has the different meaning). - {new int[3]} and {new int3} behave differently as shown above. So I suggest that - {new T[N]} would accept only a compile-time constant as N and allocate a T[N] as if T[N] were a struct type. - {new T[](n)} would allocate a T[] of length n as if T[] were a class type and had a constructor taking one size_t parameter (same as current implementation). With this semantics, {new int[2][3]} shall allocate an int[2][3], {new int[2][](3)} an int[2][] of length 3, {new int[][](2, 3)} an int[][] of length 3 having three int[] of length 2 as its elements.
Perfect. Thank you Kasumi-san. Andrei
Feb 14 2010
prev sibling next sibling parent reply Jacob Carlborg <doob me.com> writes:
On 2/14/10 19:17, Andrei Alexandrescu wrote:
 Currently new is baroque to the extreme. Should we eliminate the
 class-specific allocators in favor of a simple scheme for placement new?
 All that's really needed is to construct an object of a given type at a
 given address. All of the syntactic mess around it is unnecessary.
Didn't dsimcha or someone work on an implementation of a precise GC that needed changes to this sort of things. If so, make sure you take those changes into account.
 I think class-specific new and delete are not a useful feature.

 Second, the whole new anonymous class thing is for Java's sake. Do you
 think we need to keep all that?
Yes I think so. Removing that will break the whole DWT library.
 I suggest the following syntaxes for a type T, an integral length, an
 initializerlist a la "e1, e2, e3, ..." that could be empty, and an addr
 convertible to void*:

 new T[length]
 new T(initializerlist)
 new(addr) T[length]
 new(addr) T(initializerlist)

 and call it a day.

 What do you think?


 Andrei
Feb 15 2010
parent reply dsimcha <dsimcha yahoo.com> writes:
== Quote from Jacob Carlborg (doob me.com)'s article
 On 2/14/10 19:17, Andrei Alexandrescu wrote:
 Currently new is baroque to the extreme. Should we eliminate the
 class-specific allocators in favor of a simple scheme for placement new?
 All that's really needed is to construct an object of a given type at a
 given address. All of the syntactic mess around it is unnecessary.
Didn't dsimcha or someone work on an implementation of a precise GC that needed changes to this sort of things. If so, make sure you take those changes into account.
Here's the deal with that: 1. The patch I created supported precise scanning of the heap, but not the stack or static data segment. This probably will be enough to solve **most** false pointer problems, simply because most memory is on the heap, not the stack or static data segment. 2. Pointer offset information for each type is determined at compile time using template metaprogramming. 3. The pointer offset info needs to be passed to the GC. My patch makes it so that this information can be passed when using GC.malloc directly. However, the new operator does not get to do compile time introspection on what it's allocating. Under the hood, it's simply passed RTTI, which does not contain enough information to generate pointer offset info from. One possible remedy for this is DIP8. http://www.prowiki.org/wiki4d/wiki.cgi?LanguageDevel/DIPs/DIP8
Feb 15 2010
parent reply grauzone <none example.net> writes:
dsimcha wrote:
 2.  Pointer offset information for each type is determined at compile time
using
 template metaprogramming.
Why don't you just ask Walter to make dmd generate the necessary information?
Feb 15 2010
parent dsimcha <dsimcha yahoo.com> writes:
== Quote from grauzone (none example.net)'s article
 dsimcha wrote:
 2.  Pointer offset information for each type is determined at compile time
using
 template metaprogramming.
Why don't you just ask Walter to make dmd generate the necessary information?
Three reasons: 1. Walter has enough on his plate already. 2. Using templates to do it is both cool and practical. It's probably easier than hacking the compiler. 3. I find the fact that RTTI is such a black box and you can't customize it without hacking the compiler, despite D's incredible compile-time introspection facilities to be a weakness in the language.
Feb 15 2010
prev sibling next sibling parent reply Sean Kelly <sean invisibleduck.org> writes:
Andrei Alexandrescu Wrote:

 Currently new is baroque to the extreme. Should we eliminate the 
 class-specific allocators in favor of a simple scheme for placement new? 
 All that's really needed is to construct an object of a given type at a 
 given address. All of the syntactic mess around it is unnecessary.
 
 I think class-specific new and delete are not a useful feature.
 
 Second, the whole new anonymous class thing is for Java's sake. Do you 
 think we need to keep all that?
 
 I suggest the following syntaxes for a type T, an integral length, an 
 initializerlist a la "e1, e2, e3, ..." that could be empty, and an addr 
 convertible to void*:
 
 new T[length]
 new T(initializerlist)
 new(addr) T[length]
 new(addr) T(initializerlist)
 
 and call it a day.
 
 What do you think?
Yes, please :-) That custom allocators are currently needed for placement new just stinks. I agree with your assessment of custom allocators being problematic as well, though an alternative would be to continue allowing them as long as they accepted at least one argument (and the argument isn't size_t or whatever to avoid colliding with placement new). This would at least make custom allocator use obvious at the point of instantiation, which is how placement new works as well.
Feb 15 2010
parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Sean Kelly wrote:
 Andrei Alexandrescu Wrote:
 
 Currently new is baroque to the extreme. Should we eliminate the 
 class-specific allocators in favor of a simple scheme for placement new? 
 All that's really needed is to construct an object of a given type at a 
 given address. All of the syntactic mess around it is unnecessary.

 I think class-specific new and delete are not a useful feature.

 Second, the whole new anonymous class thing is for Java's sake. Do you 
 think we need to keep all that?

 I suggest the following syntaxes for a type T, an integral length, an 
 initializerlist a la "e1, e2, e3, ..." that could be empty, and an addr 
 convertible to void*:

 new T[length]
 new T(initializerlist)
 new(addr) T[length]
 new(addr) T(initializerlist)

 and call it a day.

 What do you think?
Yes, please :-) That custom allocators are currently needed for placement new just stinks. I agree with your assessment of custom allocators being problematic as well, though an alternative would be to continue allowing them as long as they accepted at least one argument (and the argument isn't size_t or whatever to avoid colliding with placement new). This would at least make custom allocator use obvious at the point of instantiation, which is how placement new works as well.
Walter approved. Andrei
Feb 15 2010
prev sibling parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Sun, 14 Feb 2010 13:17:44 -0500, Andrei Alexandrescu  
<SeeWebsiteForEmail erdani.org> wrote:

 Currently new is baroque to the extreme. Should we eliminate the  
 class-specific allocators in favor of a simple scheme for placement new?  
 All that's really needed is to construct an object of a given type at a  
 given address. All of the syntactic mess around it is unnecessary.

 I think class-specific new and delete are not a useful feature.

 Second, the whole new anonymous class thing is for Java's sake. Do you  
 think we need to keep all that?

 I suggest the following syntaxes for a type T, an integral length, an  
 initializerlist a la "e1, e2, e3, ..." that could be empty, and an addr  
 convertible to void*:

 new T[length]
 new T(initializerlist)
 new(addr) T[length]
 new(addr) T(initializerlist)

 and call it a day.

 What do you think?
Except for anonymous classes, that works for me. I don't think I've ever used class-specific allocators, and except for slightly ugly syntax, you can cover custom allocators with your new syntax. One thing however, let's look at how the syntax will change: auto t = new T(x, y, z); ... auto t = new(customAlloc(???)) T(x, y, z); Whatever you do for ??? to get the allocation size of T needs to be easy. I think right now, it is not a simple property of the class name, I think it should be, to make this as painless as possible. Even with that, unfortunately, you must repeat the type, which may be significant if the typename is long or complex. What about a template-ish approach? auto t = new!(alloc) T(x, y, z); where this is rewritten by the compiler to do: auto t = new(alloc!T()) T(x, y, z); Where alloc is a template function that has one type parameter, and returns an address to be passed to placement-new. This allows compile-time introspection (including David's precise scanning feature), and avoids the double specification of type. In essence, I'm adding another way to allocate, but I think it is as visible, and as easy to use, as placement new. Plus it allows any kind of introspection you wish to use on allocation. As far as anonymous classes, how do they clash with anything? I don't see the point of removing them. Yes, they are used extensively in Java because Java lacks true delegates, but there are other reasons to use it other than for callbacks. I also agree with another poster that: new T[length] might be better suited as: new T[](length) Especially in the wake of T[N] where N is a constant being considered a real value type. -Steve
Feb 15 2010
parent "Lars T. Kyllingstad" <public kyllingen.NOSPAMnet> writes:
Steven Schveighoffer wrote:
 On Sun, 14 Feb 2010 13:17:44 -0500, Andrei Alexandrescu 
 <SeeWebsiteForEmail erdani.org> wrote:
 
 Currently new is baroque to the extreme. Should we eliminate the 
 class-specific allocators in favor of a simple scheme for placement 
 new? All that's really needed is to construct an object of a given 
 type at a given address. All of the syntactic mess around it is 
 unnecessary.

 I think class-specific new and delete are not a useful feature.

 Second, the whole new anonymous class thing is for Java's sake. Do you 
 think we need to keep all that?

 I suggest the following syntaxes for a type T, an integral length, an 
 initializerlist a la "e1, e2, e3, ..." that could be empty, and an 
 addr convertible to void*:

 new T[length]
 new T(initializerlist)
 new(addr) T[length]
 new(addr) T(initializerlist)

 and call it a day.

 What do you think?
Except for anonymous classes, that works for me. I don't think I've ever used class-specific allocators, and except for slightly ugly syntax, you can cover custom allocators with your new syntax. One thing however, let's look at how the syntax will change: auto t = new T(x, y, z); ... auto t = new(customAlloc(???)) T(x, y, z); Whatever you do for ??? to get the allocation size of T needs to be easy. I think right now, it is not a simple property of the class name, I think it should be, to make this as painless as possible. Even with that, unfortunately, you must repeat the type, which may be significant if the typename is long or complex.
__traits(classInstanceSize, T) ...I think. -Lars
Feb 15 2010