digitalmars.D - Any word on the return-type const syntax?
- Janice Caron (6/6) Dec 07 2007 I know there was a suggestion in the Walter/Andrei document, but has
- Walter Bright (2/9) Dec 07 2007 That can now be done with a template.
- Janice Caron (2/3) Dec 07 2007 Not if we're talking virtual member functions, it can't.
- Christopher Wright (5/9) Dec 07 2007 I dislike that limitation of virtual methods and templates, but I don't
- Christopher Wright (40/50) Dec 08 2007 Okay, it actually isn't that hard, I think, as long as you compile your
- Jason House (2/12) Dec 07 2007 Does that mean the return keyword affecting an input parameter won't eve...
- Janice Caron (12/14) Dec 07 2007 Maybe I'm being a bit dumb here, but I just don't seem to be able to
- Walter Bright (2/14) Dec 07 2007 TransferConst!(U,T) ptr(this U)() { return a.ptr; }
- Janice Caron (47/61) Dec 08 2007 There are several things I don't understand about this example. You
- Walter Bright (12/55) Dec 08 2007 I should have written:
- Janice Caron (27/27) Dec 08 2007 But I think there's still a problem. If I write
- Walter Bright (2/17) Dec 08 2007 Template member functions are not instantiated until they are called.
- Sean Kelly (3/21) Dec 09 2007 Or until they are aliased, to be pedantic.
- Bill Baxter (5/26) Dec 09 2007 It's an important point though. Does C++ behave that way? I was under
- guslay (7/15) Dec 09 2007 Instantiation is not required with typedef, because the following is leg...
- Bill Baxter (14/34) Dec 09 2007 I think you are correct. Also C++ has a different way to do explicit
- Janice Caron (4/10) Dec 09 2007 This begs the question, will
-
Bill Baxter
(8/20)
Dec 09 2007
You keep using that phrase. I do not think it - Janice Caron (4/7) Dec 09 2007 Sorry. I meant
- Janice Caron (6/23) Dec 09 2007 I'm calling it! I'm calling it! See that line that says "auto p =
- Janice Caron (25/25) Dec 09 2007 It's no good. I just can't figure it out. Let me state a (not
- Stewart Gordon (31/70) Dec 08 2007 This doesn't work for me. Add any one (or more) of
- Janice Caron (10/15) Dec 09 2007 I /like/ this! Please can we have this syntax?
- Robert Fraser (2/23) Dec 09 2007 Agreed, I really like this idea.
- Janice Caron (4/5) Dec 09 2007 Also, you wouldn't really have to invent a new keyword! Neither
- Stewart Gordon (9/14) Dec 09 2007 (const : K) - confusing. Looks too much like a specialization.
- Janice Caron (5/22) Dec 09 2007 Yep, sorry. It should be
- Janice Caron (12/15) Dec 09 2007 No, sorry - I figured out the problem. Invariant classes and invariant
- Robert Fraser (5/8) Dec 09 2007 Link? More than half of the classes I write are invariant after
- Janice Caron (23/32) Dec 09 2007 Sorry, I can't remember, but just ask Walter for his current opinion
- =?ISO-8859-1?Q?S=F6nke_Ludwig?= (10/55) Dec 09 2007 I have actually changed a bunch of classes to be invariant, that is, the...
- Janice Caron (5/9) Dec 09 2007 Wow! I didn't know you could do that! That's actually a pretty cool feat...
- Janice Caron (19/25) Dec 08 2007 This is really key for me. A member function like
- Bill Baxter (5/15) Dec 07 2007 I was hoping the return thing would let us define virtual methods. A
- Walter Bright (2/5) Dec 07 2007 Not at the moment.
I know there was a suggestion in the Walter/Andrei document, but has it been finalised? I'm referring to the ability to define the constancy/invariance of the return type in terms of the constancy/invariance of a calling parameter, in order to avoid having to write the same function three times.
Dec 07 2007
Janice Caron wrote:I know there was a suggestion in the Walter/Andrei document, but has it been finalised? I'm referring to the ability to define the constancy/invariance of the return type in terms of the constancy/invariance of a calling parameter, in order to avoid having to write the same function three times.That can now be done with a template.
Dec 07 2007
On 12/7/07, Walter Bright <newshound1 digitalmars.com> wrote:That can now be done with a template.Not if we're talking virtual member functions, it can't.
Dec 07 2007
Janice Caron wrote:On 12/7/07, Walter Bright <newshound1 digitalmars.com> wrote:I dislike that limitation of virtual methods and templates, but I don't see a clean and efficient way around it. I should spend a couple years working on it and then publish a paper on the topic, and then submit a patch to bugzilla based on the work.That can now be done with a template.Not if we're talking virtual member functions, it can't.
Dec 07 2007
Christopher Wright wrote:Janice Caron wrote:Okay, it actually isn't that hard, I think, as long as you compile your entire application in one go. Or at least, the compiler has to have it all available at once. You don't need to send anything up the inheritance tree, but you do need to send stuff down. You'd need to get a list, for each templated method, of each instantiation; then, for each class that inherits from the base class, you'd have to adjust the vtbl appropriately. I'm not sure how templated methods work currently -- you can have an arbitrary number of instantiations for an arbitrary number of templates in a class, and those all affect the vtbl, and they have to do so in some predictable manner. Unless you make them into global functions that have the same call style as regular methods rather than putting them into the vtbl, which seems the easiest route, you have to compile the entire application in one go. This is not the current case, so I conclude that templated methods are free methods that take a this pointer. (And it's probably been mentioned here.) The vtbl is one of the main reasons that you get fast virtual method calls: one pointer dereference to get to the vtbl, one addition and a dereference to get to the method. In order to get virtual templated methods, you could use that idea, but in order to use a plain list, you'd need to fill in the vtbl at link time. That isn't actually hard, in theory, but you need a custom linker -- or more likely, add in a prelink phase to compilation just for this. Or, you could keep a special object file (or some other convenient format) somewhere for virtual templated methods. If you kept all results from template expansion there, it'd solve the problem of multiple instantiation, too. However, this also involves parsing object files -- or some other intermediate format. And it increases the size of the resulting binaries if you're compiling for multiple projects. And it does some nasty things with order of compilation with revisions, probably. And it disallows building in parallel, without some locking mechanism on the templates file. (You'd have to recompile all modules which contain classes that derive from the one with the updated list of virtual template instantiations, but that's normal, since you're effectively recompiling a module they import.) So, the method's not terribly complex, I think, but it'd be extremely annoying to work with. At the very least, you'd want template methods to be final by default so most people could ignore the whole issue.On 12/7/07, Walter Bright <newshound1 digitalmars.com> wrote:I dislike that limitation of virtual methods and templates, but I don't see a clean and efficient way around it. I should spend a couple years working on it and then publish a paper on the topic, and then submit a patch to bugzilla based on the work.That can now be done with a template.Not if we're talking virtual member functions, it can't.
Dec 08 2007
Walter Bright Wrote:Janice Caron wrote:Does that mean the return keyword affecting an input parameter won't ever be implemented? IMHO, the return keyword is more elegant than using templates.I know there was a suggestion in the Walter/Andrei document, but has it been finalised? I'm referring to the ability to define the constancy/invariance of the return type in terms of the constancy/invariance of a calling parameter, in order to avoid having to write the same function three times.That can now be done with a template.
Dec 07 2007
On 12/7/07, Jason House <jason.james.house gmail.com> wrote:Maybe I'm being a bit dumb here, but I just don't seem to be able to figure out how templates will help. Here's a typical problem. class MyArray(T) { T[] a; T* ptr() { return a.ptr; } const(T)* ptr() const { return a.ptr; } invariant(T)* ptr() invariant { return a.ptr; } } A template helps how, exactly?That can now be done with a template.Does that mean the return keyword affecting an input parameter won't ever be implemented? IMHO, the return keyword is more elegant than using templates.
Dec 07 2007
Janice Caron wrote:Here's a typical problem. class MyArray(T) { T[] a; T* ptr() { return a.ptr; } const(T)* ptr() const { return a.ptr; } invariant(T)* ptr() invariant { return a.ptr; } } A template helps how, exactly?TransferConst!(U,T) ptr(this U)() { return a.ptr; }
Dec 07 2007
On 12/8/07, Walter Bright <newshound1 digitalmars.com> wrote:Janice Caron wrote:There are several things I don't understand about this example. You seem to be suggesting that TransferConst!(U,T) resolves to K(T)* where K stands for const, invariant or nothing. That's not obvious to me, but I'll believe you. But suppose instead I had wanted a return type of K(T)[], or K(T)[int]? What then? Where is the return type? I am very confused. The next thing I don't understand is the notation ptr(this U)() How does that even parse? I'm not familiar with this means of specifying template parameters. What does it mean? The third thing I don't understand is, I see no specication of the constancy of the member function itself. I expect to see either const-at-the-end, or const-at-the-start, but I see neither. Where is it? And of course, my final question has to be, is this function still virtual? Because if it's not, I'll just carry on writing functions the old way. Cut and paste isn't /that/ bad. Let's apply the readability test now. Which is more readable? First, the current way: T* ptr() { return a.ptr; } const(T)* ptr() const { return a.ptr; } invariant(T)* ptr() invariant { return a.ptr; } Next, the way Walter suggested TransferConst!(U,T) ptr(this U)() { return a.ptr; } Next, my suggestion - replace "const" with some other symbol (here I shall write "K"), and write the function exactly once. K(T)* ptr() K { return a.ptr; } ...or, in const-at-the-front notation K K(T)* ptr() { return a.ptr } ...or, with our proposed const(this) syntax: K(this) K(T)* ptr() { return a.ptr } I think my way looks most readable, but you tell me. I don't actually care what the replacement symbol is. Obviously, "K" is an unwise choice, but you could use any reserved word (I believe "return" was suggested in your document), or even some combination of reserved words like "const in" and "const out", or whatever. (And I'd also like the symbol to be available within the body of the function). One really important point to consider is that you need EXACTLY ONE instantiation of the function. That is, the bytes of machine code which comprise the function would be identical in all three cases, and therefore need to exist only once. I suspect that your template idea, in addition to robbing me of virtuality, would also instantiate the function three times.Here's a typical problem. class MyArray(T) { T[] a; T* ptr() { return a.ptr; } const(T)* ptr() const { return a.ptr; } invariant(T)* ptr() invariant { return a.ptr; } } A template helps how, exactly?TransferConst!(U,T) ptr(this U)() { return a.ptr; }
Dec 08 2007
Janice Caron wrote:On 12/8/07, Walter Bright <newshound1 digitalmars.com> wrote:I should have written: TransferConst!(U,T*)Janice Caron wrote:There are several things I don't understand about this example. You seem to be suggesting that TransferConst!(U,T) resolves to K(T)*Here's a typical problem. class MyArray(T) { T[] a; T* ptr() { return a.ptr; } const(T)* ptr() const { return a.ptr; } invariant(T)* ptr() invariant { return a.ptr; } } A template helps how, exactly?TransferConst!(U,T) ptr(this U)() { return a.ptr; }The next thing I don't understand is the notation ptr(this U)() How does that even parse? I'm not familiar with this means of specifying template parameters. What does it mean?It means U is given the type of the 'this' pointer. This was added in 2.008.The third thing I don't understand is, I see no specication of the constancy of the member function itself. I expect to see either const-at-the-end, or const-at-the-start, but I see neither. Where is it?It's in wherever the 'this' pointer came from, i.e. from the caller.And of course, my final question has to be, is this function still virtual?No.I think my way looks most readable, but you tell me.The larger the function body is, the less readable and more error prone duplicating it becomes.One really important point to consider is that you need EXACTLY ONE instantiation of the function. That is, the bytes of machine code which comprise the function would be identical in all three cases, and therefore need to exist only once. I suspect that your template idea, in addition to robbing me of virtuality, would also instantiate the function three times.Currently, it would instantiate it three times. This is a more general problem, though, and there are many other instances where it happens. Eventually, the best solution should be in the linker being able to coalesce identical comdat sections.
Dec 08 2007
But I think there's still a problem. If I write class MyArray(T) { T[] a; TransferConst!(U,T*) ptr(this U)() { return a.ptr; } } const MyArray!(int) aa; auto p = aa.ptr; Then presumably it won't compile, becase aa is not mutable, and therefore cannot call a member function which has not been declared const. To make it compile, I'd have to change it to class MyArray(T) { T[] a; TransferConst!(U,T*) ptr(this U)() const { return a.ptr; } } But doesn't that now mean that "this" will /always/ be const within that function? Hence, if I now do MyArray!(int) aa; auto p = aa.ptr; won't the type of p end up being const(int)[] rather than int[] ?
Dec 08 2007
Janice Caron wrote:But I think there's still a problem. If I write class MyArray(T) { T[] a; TransferConst!(U,T*) ptr(this U)() { return a.ptr; } } const MyArray!(int) aa; auto p = aa.ptr; Then presumably it won't compile, becase aa is not mutable,Template member functions are not instantiated until they are called.
Dec 08 2007
Walter Bright wrote:Janice Caron wrote:Or until they are aliased, to be pedantic. SeanBut I think there's still a problem. If I write class MyArray(T) { T[] a; TransferConst!(U,T*) ptr(this U)() { return a.ptr; } } const MyArray!(int) aa; auto p = aa.ptr; Then presumably it won't compile, becase aa is not mutable,Template member functions are not instantiated until they are called.
Dec 09 2007
Sean Kelly wrote:Walter Bright wrote:It's an important point though. Does C++ behave that way? I was under the impression that in C++ I could create typedefs of templated structs and classes that wouldn't get instantiated unless actually used. --bbJanice Caron wrote:Or until they are aliased, to be pedantic.But I think there's still a problem. If I write class MyArray(T) { T[] a; TransferConst!(U,T*) ptr(this U)() { return a.ptr; } } const MyArray!(int) aa; auto p = aa.ptr; Then presumably it won't compile, becase aa is not mutable,Template member functions are not instantiated until they are called.
Dec 09 2007
Bill Baxter Wrote:Sean Kelly wrote:Instantiation is not required with typedef, because the following is legal C++ class Foo; typedef vector<Foo> vfoo_t; // 1 but not vector<Foo> vfoo; // 2 - cannot instantiate I don't know however if an implementation *would* instantiate //1 if it *could* (ie. if Foo was defined).It's an important point though. Does C++ behave that way? I was under the impression that in C++ I could create typedefs of templated structs and classes that wouldn't get instantiated unless actually used.Template member functions are not instantiated until they are called.Or until they are aliased, to be pedantic.
Dec 09 2007
guslay wrote:Bill Baxter Wrote:I think you are correct. Also C++ has a different way to do explicit instantiations: template<class T> class Array { void mf(); }; template class Array<char>; // explicit instantiation template void Array<int>::mf(); // explicit instantiation They wouldn't need that syntax if typedefs already instantiated. The instatiate-if-aliased behavior of D is a little annoying because it means you can't create convenience aliases of your templates without bloating up your executable. For linear algebra types, for instance, many C++ libraries will provide typedefs for the most common combinations of floating point type and number of components, maybe a dozen or so of these. --bbSean Kelly wrote:Instantiation is not required with typedef, because the following is legal C++ class Foo; typedef vector<Foo> vfoo_t; // 1 but not vector<Foo> vfoo; // 2 - cannot instantiate I don't know however if an implementation *would* instantiate //1 if it *could* (ie. if Foo was defined).It's an important point though. Does C++ behave that way? I was under the impression that in C++ I could create typedefs of templated structs and classes that wouldn't get instantiated unless actually used.Template member functions are not instantiated until they are called.Or until they are aliased, to be pedantic.
Dec 09 2007
On 12/9/07, Bill Baxter <dnewsgroup billbaxter.com> wrote:The instatiate-if-aliased behavior of D is a little annoying because it means you can't create convenience aliases of your templates without bloating up your executable. For linear algebra types, for instance, many C++ libraries will provide typedefs for the most common combinations of floating point type and number of components, maybe a dozen or so of these.This begs the question, will enum SomeTemplate!(int) x; instantiate the template if x is not used?
Dec 09 2007
Janice Caron wrote:On 12/9/07, Bill Baxter <dnewsgroup billbaxter.com> wrote:<voice=Inigo Montoya> You keep using that phrase. I do not think it means what you think it means.</voice>The instatiate-if-aliased behavior of D is a little annoying because it means you can't create convenience aliases of your templates without bloating up your executable. For linear algebra types, for instance, many C++ libraries will provide typedefs for the most common combinations of floating point type and number of components, maybe a dozen or so of these.This begs the question, willenum SomeTemplate!(int) x; instantiate the template if x is not used?There's definitely something needing explaining here. On the one hand new enum is supposed to be just like old enum expanded (no storage just a #define basically), and on the other its supposed to be like D2's current const storage class. --bb
Dec 09 2007
On 12/9/07, Janice Caron <caron800 googlemail.com> wrote:This begs the question, will enum SomeTemplate!(int) x;Sorry. I meant enum SomeTemplate!(int) x = something;instantiate the template if x is not used?(It'll take a while to get used to this).
Dec 09 2007
On 12/9/07, Walter Bright <newshound1 digitalmars.com> wrote:Janice Caron wrote:I'm calling it! I'm calling it! See that line that says "auto p = aa.ptr"? That (attempts to) call MyArray!(int).ptr(). However - as I said - presumably it won't compile because aa is const, and the function ptr(this U)() has not been declared as const. So there's a problem. How may this problem be fixed?But I think there's still a problem. If I write class MyArray(T) { T[] a; TransferConst!(U,T*) ptr(this U)() { return a.ptr; } } const MyArray!(int) aa; auto p = aa.ptr; Then presumably it won't compile, becase aa is not mutable,Template member functions are not instantiated until they are called.
Dec 09 2007
It's no good. I just can't figure it out. Let me state a (not uncommon) problem. See this code: class A { int[] a; this() { a.length = 4; } /* K K(int)* p() { return a.ptr } */ } A m = new A; const A c = new A; invariant A i = cast(invariant)new A; int* mp = m.p(); ++mp; const(int)* cp = c.p(); ++cp; invariant(int)* ip = i.p(); ++ip; Your task is to repace the comment inside class A, with real code, which has the effect of replacing K by "const", "invariant" or nothing. (That is, it must, in each case, return the address of a[0]). The result must compile. For the life of me, I cannot figure out how to do it. Your TransferConst! template doesn't seem to be powerful enough to do the job; I can't overload on the constancy of this ... I'm stuck! What's the answer?
Dec 09 2007
"Janice Caron" <caron800 googlemail.com> wrote in message news:mailman.263.1197106829.2338.digitalmars-d puremagic.com...On 12/8/07, Walter Bright <newshound1 digitalmars.com> wrote:This doesn't work for me. Add any one (or more) of MyArray!(int) a; const(MyArray!(int)) c; invariant(MyArray!(int)) i; and I get (DMD 2.008) transfer_const.d(7): Error: cannot implicitly convert expression (cast(int*)(this.a)) of type int* to invariant(int)*Janice Caron wrote:Here's a typical problem. class MyArray(T) { T[] a; T* ptr() { return a.ptr; } const(T)* ptr() const { return a.ptr; } invariant(T)* ptr() invariant { return a.ptr; } }It doesn't seem to exist, according to a search through the DMD and Phobos code. <snip>There are several things I don't understand about this example. You seem to be suggesting that TransferConst!(U,T)A template helps how, exactly?TransferConst!(U,T) ptr(this U)() { return a.ptr; }The next thing I don't understand is the notation ptr(this U)()http://www.digitalmars.com/d/template.html#TemplateThisParameter However, it crashes DMD when I try to use it in a class member function. Need to investigate....How does that even parse? I'm not familiar with this means of specifying template parameters. What does it mean? The third thing I don't understand is, I see no specication of the constancy of the member function itself. I expect to see either const-at-the-end, or const-at-the-start, but I see neither. Where is it?In the aforementioned (this U), I think. <snip>K(this) K(T)* ptr() { return a.ptr } I think my way looks most readable, but you tell me. I don't actually care what the replacement symbol is. Obviously, "K" is an unwise choice, but you could use any reserved word (I believe "return" was suggested in your document), or even some combination of reserved words like "const in" and "const out", or whatever. (And I'd also like the symbol to be available within the body of the function)."return" doesn't seem to make any sense. I think constness template parameters (defined as a special case that generates only one instantiation) would be a good way to go - this would also make it possible to parameterize something on the constness of more than one entity. How about K(T)* ptr(constness K : this)() { return a.ptr }One really important point to consider is that you need EXACTLY ONE instantiation of the function. That is, the bytes of machine code which comprise the function would be identical in all three cases, and therefore need to exist only once. I suspect that your template idea, in addition to robbing me of virtuality, would also instantiate the function three times.I've a vague recollection of reading somewhere that templates that differ only in constness are already defined to reduce to a single instance, but I can't seem to find it at the moment. But really, because of the possibility of bits of code being conditional on constness, we need to have both options available somehow. Stewart. -- My e-mail address is valid but not my primary mailbox. Please keep replies on the 'group where everybody may benefit.
Dec 08 2007
On 12/9/07, Stewart Gordon <smjg_1998 yahoo.com> wrote:I think constness template parameters (defined as a special case that generates only one instantiation) would be a good way to go - this would also make it possible to parameterize something on the constness of more than one entity. How about K(T)* ptr(constness K : this)() { return a.ptr }I /like/ this! Please can we have this syntax? (Except of course, the word is "constancy", not "constness". There's no such word as "constness".) For functions whose input constancy is derived from a parameter other than "this", one could write K(T)* f(constancy K)(K(T)[] a) { return a.ptr; } This is clearly much better than using any reserved word. Plus, the compiler knows to generate exactly one instantiation, with exactly three APIs.
Dec 09 2007
Janice Caron wrote:On 12/9/07, Stewart Gordon <smjg_1998 yahoo.com> wrote:Agreed, I really like this idea.I think constness template parameters (defined as a special case that generates only one instantiation) would be a good way to go - this would also make it possible to parameterize something on the constness of more than one entity. How about K(T)* ptr(constness K : this)() { return a.ptr }I /like/ this! Please can we have this syntax? (Except of course, the word is "constancy", not "constness". There's no such word as "constness".) For functions whose input constancy is derived from a parameter other than "this", one could write K(T)* f(constancy K)(K(T)[] a) { return a.ptr; } This is clearly much better than using any reserved word. Plus, the compiler knows to generate exactly one instantiation, with exactly three APIs.
Dec 09 2007
On 12/9/07, Robert Fraser <fraserofthenight gmail.com> wrote:Agreed, I really like this idea.Also, you wouldn't really have to invent a new keyword! Neither "constness" nor "constancy" is needed, because we could instead maybe do (const : K) or something. Maybe even (const K) would work?
Dec 09 2007
"Janice Caron" <caron800 googlemail.com> wrote in message news:mailman.285.1197189662.2338.digitalmars-d puremagic.com...On 12/9/07, Robert Fraser <fraserofthenight gmail.com> wrote:(const : K) - confusing. Looks too much like a specialization. (const K) - possibly ambiguous, and even if not, still confusing. Looks like it means 'an arbitrary type K, modified to be const'. Stewart. -- My e-mail address is valid but not my primary mailbox. Please keep replies on the 'group where everybody may benefit.Agreed, I really like this idea.Also, you wouldn't really have to invent a new keyword! Neither "constness" nor "constancy" is needed, because we could instead maybe do (const : K) or something. Maybe even (const K) would work?
Dec 09 2007
On 12/9/07, Stewart Gordon <smjg_1998 yahoo.com> wrote:Yep, sorry. It should be class MyArray(T:T) Walter changed the syntax between D2.007 and D2.008. Constancy of template parameters is now thrown away unless you do T:T.This doesn't work for me. Add any one (or more) of MyArray!(int) a; const(MyArray!(int)) c; invariant(MyArray!(int)) i; and I get (DMD 2.008) transfer_const.d(7): Error: cannot implicitly convert expression (cast(int*)(this.a)) of type int* to invariant(int)*Here's a typical problem. class MyArray(T) { T[] a; T* ptr() { return a.ptr; } const(T)* ptr() const { return a.ptr; } invariant(T)* ptr() invariant { return a.ptr; } }
Dec 09 2007
On 12/9/07, Janice Caron <caron800 googlemail.com> wrote:No, sorry - I figured out the problem. Invariant classes and invariant member functions make no sense. This was discussed in another thread somewhere, and Walter agreed. So in fact, you only have to consider the const and non-const instantiations. You can forget the invariant one. So, in fact, you only need class MyArray(T) { T[] a; T* ptr() { return a.ptr; } const(T)* ptr() const { return a.ptr; } }transfer_const.d(7): Error: cannot implicitly convert expression (cast(int*)(this.a)) of type int* to invariant(int)*Yep, sorry. It should be
Dec 09 2007
Janice Caron wrote:No, sorry - I figured out the problem. Invariant classes and invariant member functions make no sense. This was discussed in another thread somewhere, and Walter agreed.Link? More than half of the classes I write are invariant after construction, and having the compiler be able to optimize that would be great (Java 6's HotSpot can, after all, without any special marking in the code).
Dec 09 2007
On 12/9/07, Robert Fraser <fraserofthenight gmail.com> wrote:Janice Caron wrote:Sorry, I can't remember, but just ask Walter for his current opinion (and if it's different from his previous opinion, so be it). Basically, it boils down to the fact that invariant C = new C; won't compile, because mutable won't implicitly convert to invariant. For that, you'd need Walter to add a language construct like invariant C = inew C; ...which of course doesn't exist. I know you could always write invariant C = cast(invariant(C)) new C; but casts are a last resort, as they're error-prone. Assuming we decide we /do/ have to support invariant classes after all, then the compiler was correct to flag the error that it did. The line in question wasNo, sorry - I figured out the problem. Invariant classes and invariant member functions make no sense. This was discussed in another thread somewhere, and Walter agreed.Link? More than half of the classes I write are invariant after construction, and having the compiler be able to optimize that would be great (Java 6's HotSpot can, after all, without any special marking in the code).and that error arises because T* (the type of a.ptr) will not implicitly convert to invariant(T)*. If you really wanted to support invariant classes, that line would have to be changed to: invariant(T)* ptr() invariant { return cast(invariant(T)*) a.ptr; } Simply put - invariant classes lead to lots of casting. And they're pointless anyway, because Walter said (...and I'm sorry, I can't find you a link, but I'm sure he'll read this and correct me if I'm wrong...) that invariant classes don't help with optimization anyway, so why bother with them?invariant(T)* ptr() invariant { return a.ptr; }
Dec 09 2007
Janice Caron wrote:On 12/9/07, Robert Fraser <fraserofthenight gmail.com> wrote:I have actually changed a bunch of classes to be invariant, that is, they are declared as "invariant class C {}". At least, if they are used like this, no extra casts are necessary. "new C" works, and inside of the class nothing needs to be manually declared invariant using a cast. The main benefit here is not compiler optimization, but by knowing some instance is invariant, you can use this instance from any number of threads without worrying about locking/synchronization. I think this can sometimes be a very useful feature to enforce instance invariantness in the language (and to document it at the same time).Janice Caron wrote:Sorry, I can't remember, but just ask Walter for his current opinion (and if it's different from his previous opinion, so be it). Basically, it boils down to the fact that invariant C = new C; won't compile, because mutable won't implicitly convert to invariant. For that, you'd need Walter to add a language construct like invariant C = inew C; ...which of course doesn't exist. I know you could always write invariant C = cast(invariant(C)) new C; but casts are a last resort, as they're error-prone. Assuming we decide we /do/ have to support invariant classes after all, then the compiler was correct to flag the error that it did. The line in question wasNo, sorry - I figured out the problem. Invariant classes and invariant member functions make no sense. This was discussed in another thread somewhere, and Walter agreed.Link? More than half of the classes I write are invariant after construction, and having the compiler be able to optimize that would be great (Java 6's HotSpot can, after all, without any special marking in the code).and that error arises because T* (the type of a.ptr) will not implicitly convert to invariant(T)*. If you really wanted to support invariant classes, that line would have to be changed to: invariant(T)* ptr() invariant { return cast(invariant(T)*) a.ptr; } Simply put - invariant classes lead to lots of casting. And they're pointless anyway, because Walter said (...and I'm sorry, I can't find you a link, but I'm sure he'll read this and correct me if I'm wrong...) that invariant classes don't help with optimization anyway, so why bother with them?invariant(T)* ptr() invariant { return a.ptr; }
Dec 09 2007
On Dec 9, 2007 11:36 PM, Sönke Ludwig <ludwig informatik_dot_uni-luebeck.de> wrote:I have actually changed a bunch of classes to be invariant, that is, they are declared as "invariant class C {}". At least, if they are used like this, no extra casts are necessary. "new C" works, and inside of the class nothing needs to be manually declared invariant using a cast.Wow! I didn't know you could do that! That's actually a pretty cool feature! OK, so there /is/ language support. That means I was wrong, and you can forget everything I ever said about invariant classes.
Dec 09 2007
On 12/8/07, Janice Caron <caron800 googlemail.com> wrote:One really important point to consider is that you need EXACTLY ONE instantiation of the function. That is, the bytes of machine code which comprise the function would be identical in all three cases, and therefore need to exist only once. I suspect that your template idea, in addition to robbing me of virtuality, would also instantiate the function three times.This is really key for me. A member function like K(T)[] f() { /*...*/ } K where K stands for const, invariant, or nothing, needs exactly one instantiation, not three, though it may generate three distinct APIs. Also, there's no reason why it can't be virtual. Templates would not only generate three distinct instantiations, they would rob us of of virtuality. Let's go back to the array example. I could write a /single/ function class MyArray(T) { T[] a; const(T)* ptr() const { return a.ptr; } } with the knowledge that I could safely do MyArray!(int) a; int* ptr = cast(int*)a.ptr; because I have a priori knowledge that a is not const. It should be possible to encapsulate that knowledge in the function definition.
Dec 08 2007
Walter Bright wrote:Janice Caron wrote:I was hoping the return thing would let us define virtual methods. A template solution won't allow that currently. Is there a plan to change that? --bbI know there was a suggestion in the Walter/Andrei document, but has it been finalised? I'm referring to the ability to define the constancy/invariance of the return type in terms of the constancy/invariance of a calling parameter, in order to avoid having to write the same function three times.That can now be done with a template.
Dec 07 2007
Bill Baxter wrote:I was hoping the return thing would let us define virtual methods. A template solution won't allow that currently. Is there a plan to change that?Not at the moment.
Dec 07 2007