digitalmars.D - operator new(): struct v. class
- C. Dunn (12/23) Aug 17 2007 Walter, could you please address this? I have no problem at all with yo...
- Kirk McDonald (21/59) Aug 17 2007 It's a trivial bit of template code. Something like this:
- C. Dunn (5/37) Aug 20 2007 Someone who can figure it out does not need to. I think that's why peop...
- Kirk McDonald (21/68) Aug 20 2007 It's the IsExpression:
- Bill Baxter (31/91) Aug 20 2007 Which I think is a top contender in the running for the weirdest syntax
- Kirk McDonald (11/22) Aug 20 2007 It is ambiguous. Both sides of a comparison must be an expression, and
- BCS (4/25) Aug 20 2007 Would it? The syntax could be defined as:
- Don Clugston (8/26) Sep 04 2007 Ideally, I think, we'd have a merge between is() and typeof()/typeid()
- Jari-Matti =?ISO-8859-1?Q?M=E4kel=E4?= (17/46) Sep 07 2007 Even now you can't tell whether e.g. 'a = b' is syntactically correct
Walter, could you please address this? I have no problem at all with your design decisions. All I want is an operator New() that the compiler will understand, and which allows me to compare the performance of struct pointers to classes. I have outlined the issue below: Walter Bright Wrote:James Dennett wrote:But Walter, how did you handle operator new()? It needs to be agnostic about class/struct. class C{int x;}; stuct S{int x;}; typedef C MyType; //typedef S* MyType; MyType inst = new MyType; If you use the second typedef, this will not compile! That is the problem. Why not provide an operator New() which expects a pointer type when used for structs? Just have the compiler translate it. I cannot see how to write such a generic operator New() myself. This one small change would be a great boon to any C/C++ programmer thinking of adopting D.Walter Bright wrote:That isn't my experience. In my work on DMDscript in D, I changed some types between struct and class to try out some variations, and found it to be a lot easier than in C++. For one thing, I didn't have to find and edit all the -> and .'s.Value types are fundamentally different from reference types. D gives you the choice.C++ gives you *more* choice by allowing easier migration between the two without imposing performance or syntactic differences.
Aug 17 2007
C. Dunn wrote:Walter, could you please address this? I have no problem at all with your design decisions. All I want is an operator New() that the compiler will understand, and which allows me to compare the performance of struct pointers to classes. I have outlined the issue below: Walter Bright Wrote:It's a trivial bit of template code. Something like this: T New(T)() { static if (is(T U == U*)) { return new U; } else { return new T; } } class C {} struct S {} void main() { C c = New!(C); S* s = New!(S*); } Handling constructor arguments, too, is only a little more complicated. -- Kirk McDonald http://kirkmcdonald.blogspot.com Pyd: Connecting D and Python http://pyd.dsource.orgJames Dennett wrote:But Walter, how did you handle operator new()? It needs to be agnostic about class/struct. class C{int x;}; stuct S{int x;}; typedef C MyType; //typedef S* MyType; MyType inst = new MyType; If you use the second typedef, this will not compile! That is the problem. Why not provide an operator New() which expects a pointer type when used for structs? Just have the compiler translate it. I cannot see how to write such a generic operator New() myself. This one small change would be a great boon to any C/C++ programmer thinking of adopting D.Walter Bright wrote:That isn't my experience. In my work on DMDscript in D, I changed some types between struct and class to try out some variations, and found it to be a lot easier than in C++. For one thing, I didn't have to find and edit all the -> and .'s.Value types are fundamentally different from reference types. D gives you the choice.C++ gives you *more* choice by allowing easier migration between the two without imposing performance or syntactic differences.
Aug 17 2007
Kirk McDonald Wrote:I don't understand your static if expression. Where in the docs is there an explanation for "is(T U == U*)"? I completely missed that, and I really do not understand what it does.But Walter, how did you handle operator new()? It needs to be agnostic about class/struct. class C{int x;}; stuct S{int x;}; typedef C MyType; //typedef S* MyType; MyType inst = new MyType; If you use the second typedef, this will not compile! That is the problem. Why not provide an operator New() which expects a pointer type when used for structs? Just have the compiler translate it. I cannot see how to write such a generic operator New() myself.It's a trivial bit of template code. Something like this: T New(T)() { static if (is(T U == U*)) { return new U; } else { return new T; } } class C {} struct S {} void main() { C c = New!(C); S* s = New!(S*); }Handling constructor arguments, too, is only a little more complicated.Someone who can figure it out does not need to. I think that's why people are ignoring my concern. It's disregard for the novice. If y'all want C++ programmers to adopt D, you have to make it easy. C++ is entrenched. This operator new() issue and the lack of a stack trace from an exception thrown during contract-checking weaken the arguments for adoption. Maybe someday these will be addressed. D certainly has potential. And yes, before anybody mentions it, flectioned is really cool. If it gets integrated into tango, and if tango is released for D 2.0, then the stack-trace issue might disappear. Then maybe tango will provide an operator New().
Aug 20 2007
C. Dunn wrote:Kirk McDonald Wrote:It's the IsExpression: http://www.digitalmars.com/d/expression.html#IsExpression Specifically, it's this form of the IsExpression: is ( Type Identifier == TypeSpecialization ) "The condition is satisfied if Type is semantically correct and is the same as TypeSpecialization. The Identifier is declared to be either an alias of the TypeSpecialization or, if TypeSpecialization is dependent on Identifier, the deduced type." That is, if T can be expressed as U*, is() evaluates to true, and U is declared to be an alias to the appropriate type.I don't understand your static if expression. Where in the docs is there an explanation for "is(T U == U*)"? I completely missed that, and I really do not understand what it does.But Walter, how did you handle operator new()? It needs to be agnostic about class/struct. class C{int x;}; stuct S{int x;}; typedef C MyType; //typedef S* MyType; MyType inst = new MyType; If you use the second typedef, this will not compile! That is the problem. Why not provide an operator New() which expects a pointer type when used for structs? Just have the compiler translate it. I cannot see how to write such a generic operator New() myself.It's a trivial bit of template code. Something like this: T New(T)() { static if (is(T U == U*)) { return new U; } else { return new T; } } class C {} struct S {} void main() { C c = New!(C); S* s = New!(S*); }I don't understand what you mean by this.Handling constructor arguments, too, is only a little more complicated.Someone who can figure it out does not need to.I think that's why people are ignoring my concern. It's disregard for the novice. If y'all want C++ programmers to adopt D, you have to make it easy. C++ is entrenched. This operator new() issue and the lack of a stack trace from an exception thrown during contract-checking weaken the arguments for adoption. Maybe someday these will be addressed. D certainly has potential. And yes, before anybody mentions it, flectioned is really cool. If it gets integrated into tango, and if tango is released for D 2.0, then the stack-trace issue might disappear. Then maybe tango will provide an operator New().The above is quite easy... assuming you know about the appropriate tools. The IsExpression is one of D's most powerful compile-time tools. If you're doing any generic programming in D, it is one of the first things you should learn about. -- Kirk McDonald http://kirkmcdonald.blogspot.com Pyd: Connecting D and Python http://pyd.dsource.org
Aug 20 2007
Kirk McDonald wrote:C. Dunn wrote:Which I think is a top contender in the running for the weirdest syntax ever devised for a construct in a C-derived language. It's basically an is(Type==TypeSpecialization) that includes type deduction. You're not comparing Identifier with TypeSpecialization so it's bizarre to write anything that looks like U==U*. Obviously U is not U* for any value of U. Any of the following would look more sensible if you ask me: either put the Identifier first is(U : Type == U*) is(U ; Type == U*) is(U | Type == U*) is(U <- Type == U*) or put it last is(Type == U* U) is(Type == U* : U) is(Type == U* | U) is(Type == U* -> U) is(Type == U* with U) or use template syntax is!(U)(Type==U*) And why do we even need is() to do basic type comparisons anyway? What's ambiguous about static if( MyType == OtherType ) { ... } ? I guess you could define a static opEquals, but A) that's useless enough that it could be outlawed B) it wouldn't take a type as an argument so it still wouldn't be ambiguous. --bbKirk McDonald Wrote:It's the IsExpression: http://www.digitalmars.com/d/expression.html#IsExpression Specifically, it's this form of the IsExpression: is ( Type Identifier == TypeSpecialization ) "The condition is satisfied if Type is semantically correct and is the same as TypeSpecialization. The Identifier is declared to be either an alias of the TypeSpecialization or, if TypeSpecialization is dependent on Identifier, the deduced type." That is, if T can be expressed as U*, is() evaluates to true, and U is declared to be an alias to the appropriate type.I don't understand your static if expression. Where in the docs is there an explanation for "is(T U == U*)"? I completely missed that, and I really do not understand what it does.But Walter, how did you handle operator new()? It needs to be agnostic about class/struct. class C{int x;}; stuct S{int x;}; typedef C MyType; //typedef S* MyType; MyType inst = new MyType; If you use the second typedef, this will not compile! That is the problem. Why not provide an operator New() which expects a pointer type when used for structs? Just have the compiler translate it. I cannot see how to write such a generic operator New() myself.It's a trivial bit of template code. Something like this: T New(T)() { static if (is(T U == U*)) { return new U; } else { return new T; } } class C {} struct S {} void main() { C c = New!(C); S* s = New!(S*); }
Aug 20 2007
Bill Baxter wrote:And why do we even need is() to do basic type comparisons anyway? What's ambiguous about static if( MyType == OtherType ) { ... } ? I guess you could define a static opEquals, but A) that's useless enough that it could be outlawed B) it wouldn't take a type as an argument so it still wouldn't be ambiguous. --bbIt is ambiguous. Both sides of a comparison must be an expression, and types are not expressions. Allowing that would mean you couldn't determine whether 'MyType' is an expression or a type until after the syntactic pass. This would break some cardinal rules about the ease with which you can parse D code. -- Kirk McDonald http://kirkmcdonald.blogspot.com Pyd: Connecting D and Python http://pyd.dsource.org
Aug 20 2007
Reply to Kirk,Bill Baxter wrote:Would it? The syntax could be defined as: CompExp ::= TypeOrExp '==' TypeOrExp; and then wait for the semantic pass to check what is actually used.And why do we even need is() to do basic type comparisons anyway? What's ambiguous about static if( MyType == OtherType ) { ... } ? I guess you could define a static opEquals, but A) that's useless enough that it could be outlawed B) it wouldn't take a type as an argument so it still wouldn't be ambiguous. --bbIt is ambiguous. Both sides of a comparison must be an expression, and types are not expressions. Allowing that would mean you couldn't determine whether 'MyType' is an expression or a type until after the syntactic pass. This would break some cardinal rules about the ease with which you can parse D code.
Aug 20 2007
Kirk McDonald wrote:Bill Baxter wrote:Ideally, I think, we'd have a merge between is() and typeof()/typeid() static if (typeid(MyType)==typeid(OtherType)) { } There are quite a few cases where we have syntax which is completely different at run-time compared to compile compile-time, yet which do exactly the same thing. __traits and typeinfo seem to be awfully similar, for example. If they were unified, CTFE could grab even more territory from templates.And why do we even need is() to do basic type comparisons anyway? What's ambiguous about static if( MyType == OtherType ) { ... } ? I guess you could define a static opEquals, but A) that's useless enough that it could be outlawed B) it wouldn't take a type as an argument so it still wouldn't be ambiguous. --bbIt is ambiguous. Both sides of a comparison must be an expression, and types are not expressions. Allowing that would mean you couldn't determine whether 'MyType' is an expression or a type until after the syntactic pass. This would break some cardinal rules about the ease with which you can parse D code.
Sep 04 2007
Don Clugston wrote:Kirk McDonald wrote:Even now you can't tell whether e.g. 'a = b' is syntactically correct without several passes of semantic analysis: template z(string x, string y){mixin(`mixin("template c(string T){mixin(\"alias \"~T~\" t;\");}");c!("int").t `~x~`; int s( string a) { return a.length ? 1 + s(a[1..$]) : 0; } auto ` ~y~`= s(x~y);`);}mixin z!("a","b"); void main() { a = b; }Bill Baxter wrote:And why do we even need is() to do basic type comparisons anyway? What's ambiguous about static if( MyType == OtherType ) { ... } ? I guess you could define a static opEquals, but A) that's useless enough that it could be outlawed B) it wouldn't take a type as an argument so it still wouldn't be ambiguous. --bbIt is ambiguous. Both sides of a comparison must be an expression, and types are not expressions. Allowing that would mean you couldn't determine whether 'MyType' is an expression or a type until after the syntactic pass. This would break some cardinal rules about the ease with which you can parse D code.Ideally, I think, we'd have a merge between is() and typeof()/typeid() static if (typeid(MyType)==typeid(OtherType)) { }I find the idea of comparing types directly more natural. Compile time metaobjects feel really intriguing in general. However, I feel sorry for Walter. Implementing all this some day must be tiresome :)There are quite a few cases where we have syntax which is completely different at run-time compared to compile compile-time, yet which do exactly the same thing. __traits and typeinfo seem to be awfully similar, for example.If one the main design principles of D was the principle of least surprise, is expression would have been buried long time ago. Honestly, it has one of the weirdest syntax and semantics.If they were unified, CTFE could grab even more territory from templates.As long as CTFE and/or string mixins can't handle alias parameters there will be need for templates (and/or macros).
Sep 07 2007