| Thread overview | |||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
February 09, 2008 Question about explicit template instantiation | ||||
|---|---|---|---|---|
| ||||
I am working my way throught the pdf documentation ( 1.0 ) regarding templates in D and in the topic about explicit template instantiation and I came across the lines below, which have me stumped: ---------------------------------------------------------------- A template instantiation can be aliased: template TFoo(T) { alias T* t; } alias TFoo!(int) abc; abc.t x; // declare x to be of type int* Multiple instantiations of a TemplateDeclaration with the same TemplateArgumentList, before implicit conversions, all will refer to the same instantiation. For example: template TFoo(T) { T f; } alias TFoo!(int) a; alias TFoo!(int) b; ... a.f = 3; assert(b.f == 3); // a and b refer to the same instance of TFoo This is true even if the TemplateInstances are done in different modules. ---------------------------------------------------------------- My confusion with the above is that an alias, when referring to a type, is the equivalent of a C++ typedef AFAICS. So 'a' and 'b' above are types ( because the instantiated template is a type ) and then I see the 'a.f=3' line followed by the 'assert(b.f == 3)' line and I can not understand how a type can be used in either expression. I am also assuming that the line beginning with "Multiple instantiations of a..." only mean that the 'a' and 'b' refer to the same type, but perhaps I have missed something in this explanation. | ||||
February 10, 2008 Re: Question about explicit template instantiation | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Edward Diener | Edward Diener さんは書きました:
> I am working my way throught the pdf documentation ( 1.0 ) regarding templates in D and in the topic about explicit template instantiation and I came across the lines below, which have me stumped:
>
> ----------------------------------------------------------------
>
> A template instantiation can be aliased:
> template TFoo(T) { alias T* t; }
> alias TFoo!(int) abc;
> abc.t x; // declare x to be of type int*
> Multiple instantiations of a TemplateDeclaration with the same TemplateArgumentList, before
> implicit conversions, all will refer to the same instantiation. For example:
> template TFoo(T) { T f; }
> alias TFoo!(int) a;
> alias TFoo!(int) b;
> ...
>
> a.f = 3;
> assert(b.f == 3); // a and b refer to the same instance of TFoo
> This is true even if the TemplateInstances are done in different modules.
>
> ----------------------------------------------------------------
>
> My confusion with the above is that an alias, when referring to a type, is the equivalent of a C++ typedef AFAICS. So 'a' and 'b' above are types ( because the instantiated template is a type ) and then I see the 'a.f=3' line followed by the 'assert(b.f == 3)' line and I can not understand how a type can be used in either expression.
>
> I am also assuming that the line beginning with "Multiple instantiations of a..." only mean that the 'a' and 'b' refer to the same type, but perhaps I have missed something in this explanation.
The problem here is that you are misconstruing templates to be classes. Templates, like classes and other types, can be aliased, however since a template is not a type you couldn't use TFoo!(int) to declare a variable. This also applies to the derived aliases 'a' and 'b'.
The templated class however, is a different story. Take the following code snipet for example:
class Bar(T)
{
T f;
}
alias bar!(int) y;
alias bar!(int) z;
Here Bar(T) is a class, therefore Bar!(int) is a class instanciation: a type. Hence, the aliases, 'y' and 'z' are also types. Any attempts to use them as with the previous example, will result in an error.
y.f = 3; // Error y is an instanciated class
assert(z.f == 3); // Error y is an instanciated class
Proper usage in this case is the same as any other class:
y Y; // OK
Y.f = 3; // Error memory not yet allocated for Y
Y = new y; // OK
Y.f = 3; // OK
assert(Y.f == 3); //OK
Hope that helps somewhat!
| |||
February 10, 2008 Re: Question about explicit template instantiation | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Tyro[a.c.edwards] | Tyro[a.c.edwards] wrote: > Edward Diener さんは書きました: >> I am working my way throught the pdf documentation ( 1.0 ) regarding templates in D and in the topic about explicit template instantiation and I came across the lines below, which have me stumped: >> >> ---------------------------------------------------------------- >> >> A template instantiation can be aliased: >> template TFoo(T) { alias T* t; } >> alias TFoo!(int) abc; >> abc.t x; // declare x to be of type int* >> Multiple instantiations of a TemplateDeclaration with the same TemplateArgumentList, before >> implicit conversions, all will refer to the same instantiation. For example: >> template TFoo(T) { T f; } >> alias TFoo!(int) a; >> alias TFoo!(int) b; >> ... >> >> a.f = 3; >> assert(b.f == 3); // a and b refer to the same instance of TFoo >> This is true even if the TemplateInstances are done in different modules. >> >> ---------------------------------------------------------------- >> >> My confusion with the above is that an alias, when referring to a type, is the equivalent of a C++ typedef AFAICS. So 'a' and 'b' above are types ( because the instantiated template is a type ) and then I see the 'a.f=3' line followed by the 'assert(b.f == 3)' line and I can not understand how a type can be used in either expression. >> >> I am also assuming that the line beginning with "Multiple instantiations of a..." only mean that the 'a' and 'b' refer to the same type, but perhaps I have missed something in this explanation. > > The problem here is that you are misconstruing templates to be classes. Templates, like classes and other types, can be aliased, however since a template is not a type you couldn't use TFoo!(int) to declare a variable. This also applies to the derived aliases 'a' and 'b'. I understand what a template is and that the instantiation of a template is a type ( class ). So in the example above 'a' and 'b' are aliases for types, ie. typedef in C++. Therefore the statements "a.f = 3;" and 'assert(b.f == 3);" made no sense to me. But I think I understand them now, but hopefully someone will clarify things for me. It seems in D one can instantiate a temporary object from a type which has a default constructor simply by using the type, whereas in C++ one must use the type followed by '()'. So whereas if X were a class with a default constructor with the data member Y, in C++ one would use 'X().Y' to access the temporary's Y data member while in D it appears one can use 'X.Y' to access the temporary's data member. The previous explanation is the only way I can make sense of the two statements above which led to my OP. > > The templated class however, is a different story. Take the following code snipet for example: > > class Bar(T) > { > T f; > } > > alias bar!(int) y; > alias bar!(int) z; > > Here Bar(T) is a class, therefore Bar!(int) is a class instanciation: a type. Hence, the aliases, 'y' and 'z' are also types. Any attempts to use them as with the previous example, will result in an error. > > y.f = 3; // Error y is an instanciated class > assert(z.f == 3); // Error y is an instanciated class What I quoted in my OP was all directly from the documentation, not anything I made up. Somehow you think that the lines: a.f = 3; assert(b.f == 3); // a and b refer to the same instance of TFoo were inserted by me. No ! They were in the doc and they appeared to be incorrect, and I wanted an explanation for them. | |||
February 10, 2008 Re: Question about explicit template instantiation | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Edward Diener | On 10/02/2008, Edward Diener <eddielee_no_spam_here@tropicsoft.com> wrote: > But I think I understand them now, but hopefully someone will clarify things for me. It seems in D one can instantiate a temporary object from a type which has a default constructor simply by using the type, whereas in C++ one must use the type followed by '()'. So whereas if X were a class with a default constructor with the data member Y, in C++ one would use 'X().Y' to access the temporary's Y data member while in D it appears one can use 'X.Y' to access the temporary's data member. Alas no. You can omit the brackets, but you cannot omit the word "new". Thus, it would be either new X().Y or (new X).Y A template is not necessarily a class. You can have template classes, but not all templates are classes. You can also have template functions, but not all templates are functions. The most general statement would probably be that a template is a namespace. Thus: template MyNamespace(T) { int x; } generates a different namespace for each different type of T. So in the above example, x is a global variable, not a member variable, within MyNamespace!(T) for some T. Therefore: MyNamesspace!(int).x is a different variable from MyNamespace!(double).x because the Ts are different. If I choose to save typing by writing: alias MyNamespace!(int) A; alias MyNamespace!(double) B; then A.x and B.x would still be different global variables. However, if I later write alias MyNamespace!(int) C; then C refers to the /same/ namespace as A, and hence A.x and C.x are the exact same global variable. | |||
February 10, 2008 Re: Question about explicit template instantiation | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Edward Diener | "Edward Diener" <eddielee_no_spam_here@tropicsoft.com> wrote in message news:foleie$67q$1@digitalmars.com... >I am working my way throught the pdf documentation ( 1.0 ) regarding templates in D and in the topic about explicit template instantiation and I came across the lines below, which have me stumped: > > ---------------------------------------------------------------- > > A template instantiation can be aliased: > template TFoo(T) { alias T* t; } > alias TFoo!(int) abc; > abc.t x; // declare x to be of type int* > Multiple instantiations of a TemplateDeclaration with the same > TemplateArgumentList, before > implicit conversions, all will refer to the same instantiation. For > example: > template TFoo(T) { T f; } > alias TFoo!(int) a; > alias TFoo!(int) b; > ... > > a.f = 3; > assert(b.f == 3); // a and b refer to the same instance of TFoo > This is true even if the TemplateInstances are done in different modules. > > ---------------------------------------------------------------- > > My confusion with the above is that an alias, when referring to a type, is the equivalent of a C++ typedef AFAICS. So 'a' and 'b' above are types ( because the instantiated template is a type ) and then I see the 'a.f=3' line followed by the 'assert(b.f == 3)' line and I can not understand how a type can be used in either expression. Aliases are a superset of the C/C++ typedef. An alias is much more general, allowing you to not only rename types, but more generally, create a new symbol (name) that refers to another symbol. This way, you can alias types, template instantiations, functions, methods, modules, etc. etc. What's happening here is that TFoo is not a type, and an instance of TFoo is not a type either. TFoo, when instantiated, is more like a namespace. It has a single variable, f. This is not a field or anything, it's just a variable. When you instantiate TFoo with a type, you basically declare a global variable TFoo!(T).f. So: template TFoo(T) { T f; } void foo() { alias TFoo!(int) a; a.f++; Stdout.formatln("{}", a.f); } void main() { foo(); foo(); } prints 1 and 2. Notice that even though 'a' was aliased inside foo(), it's kind of like a static variable. Contrast this with mixins, where the declarations are inserted at the instantiation location: void foo() { mixin TFoo!(int) a; a.f++; Stdout.formatln("{}", a.f); } This prints 1 and 1, since a.f is now basically a local variable. > I am also assuming that the line beginning with "Multiple instantiations of a..." only mean that the 'a' and 'b' refer to the same type, but perhaps I have missed something in this explanation. a and b refer to the same *symbol*, yes. But instantiations of TFoo are not types. | |||
February 10, 2008 Re: Question about explicit template instantiation | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Janice Caron | Janice Caron wrote: > On 10/02/2008, Edward Diener <eddielee_no_spam_here@tropicsoft.com> wrote: >> But I think I understand them now, but hopefully someone will clarify >> things for me. It seems in D one can instantiate a temporary object from >> a type which has a default constructor simply by using the type, whereas >> in C++ one must use the type followed by '()'. So whereas if X were a >> class with a default constructor with the data member Y, in C++ one >> would use 'X().Y' to access the temporary's Y data member while in D it >> appears one can use 'X.Y' to access the temporary's data member. > > Alas no. You can omit the brackets, but you cannot omit the word > "new". Thus, it would be either > > new X().Y > > or > > (new X).Y Understood. I forgot all non-struct classes must be in GC memory. > > A template is not necessarily a class. You can have template classes, > but not all templates are classes. You can also have template > functions, but not all templates are functions. The most general > statement would probably be that a template is a namespace. Thus: > > template MyNamespace(T) > { > int x; > } A template being a namespace in D is certainly different from C++. > > generates a different namespace for each different type of T. So in > the above example, x is a global variable, not a member variable, > within MyNamespace!(T) for some T. Therefore: > > MyNamesspace!(int).x > > is a different variable from > > MyNamespace!(double).x > > because the Ts are different. If I choose to save typing by writing: > > alias MyNamespace!(int) A; > alias MyNamespace!(double) B; > > then A.x and B.x would still be different global variables. However, > if I later write > > alias MyNamespace!(int) C; > > then C refers to the /same/ namespace as A, and hence A.x and C.x are > the exact same global variable. This is confusing to me coming from C++. In C++ instantiating a class template produces a type. Is that not the way D works ? If not, what does instantiating a template produce in D and, if it does not produce a type, how does one instantiate a template which does produce a type in D ? | |||
February 10, 2008 Re: Question about explicit template instantiation | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Jarrett Billingsley | Jarrett Billingsley wrote: > "Edward Diener" <eddielee_no_spam_here@tropicsoft.com> wrote in message news:foleie$67q$1@digitalmars.com... >> I am working my way throught the pdf documentation ( 1.0 ) regarding templates in D and in the topic about explicit template instantiation and I came across the lines below, which have me stumped: >> >> ---------------------------------------------------------------- >> >> A template instantiation can be aliased: >> template TFoo(T) { alias T* t; } >> alias TFoo!(int) abc; >> abc.t x; // declare x to be of type int* >> Multiple instantiations of a TemplateDeclaration with the same TemplateArgumentList, before >> implicit conversions, all will refer to the same instantiation. For example: >> template TFoo(T) { T f; } >> alias TFoo!(int) a; >> alias TFoo!(int) b; >> ... >> >> a.f = 3; >> assert(b.f == 3); // a and b refer to the same instance of TFoo >> This is true even if the TemplateInstances are done in different modules. >> >> ---------------------------------------------------------------- >> >> My confusion with the above is that an alias, when referring to a type, is the equivalent of a C++ typedef AFAICS. So 'a' and 'b' above are types ( because the instantiated template is a type ) and then I see the 'a.f=3' line followed by the 'assert(b.f == 3)' line and I can not understand how a type can be used in either expression. > > Aliases are a superset of the C/C++ typedef. An alias is much more general, allowing you to not only rename types, but more generally, create a new symbol (name) that refers to another symbol. This way, you can alias types, template instantiations, functions, methods, modules, etc. etc. Understood. > > What's happening here is that TFoo is not a type, and an instance of TFoo is not a type either. > TFoo, when instantiated, is more like a namespace. It has a single variable, f. This is not a field or anything, it's just a variable. When you instantiate TFoo with a type, you basically declare a global variable TFoo!(T).f. So: > > template TFoo(T) > { > T f; > } > > void foo() > { > alias TFoo!(int) a; > a.f++; > Stdout.formatln("{}", a.f); > } > > void main() > { > foo(); > foo(); > } > > prints 1 and 2. Notice that even though 'a' was aliased inside foo(), it's kind of like a static variable. This is utterly confusing to me coming from C++. Instantiating templates in C++ produce a type. If a template instantiation is not a type, what is it ? Also how does one produce a type from a template in D ? > > Contrast this with mixins, where the declarations are inserted at the instantiation location: > > void foo() > { > mixin TFoo!(int) a; > a.f++; > Stdout.formatln("{}", a.f); > } > > This prints 1 and 1, since a.f is now basically a local variable. I will tackle mixins once I understand D templates, but I am now lost. > >> I am also assuming that the line beginning with "Multiple instantiations of a..." only mean that the 'a' and 'b' refer to the same type, but perhaps I have missed something in this explanation. > > a and b refer to the same *symbol*, yes. But instantiations of TFoo are not types. Thanks for the information but I await your and Janice's response about what a template instantiation is. I admit I am lost now with D templates and the doc sure did not prepare me for whatever a template instantiation is supposed to be. | |||
February 10, 2008 Re: Question about explicit template instantiation | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Edward Diener | On 10/02/2008, Edward Diener <eddielee_no_spam_here@tropicsoft.com> wrote: > > template MyNamespace(T) > > { > > int x; > > } > This is confusing to me coming from C++. In C++ instantiating a class template produces a type. Is that not the way D works ? That's /exactly/ the way that D works. With CLASS templates, D works just like C++. No problem. Compare: c++ template<class T> class A { int x; }; A<int> a1; A<double> a2; and the D equivalent: class A(T) { int x; } auto a1 = new A!(int); auto a2 = new A!(double); They're exactly the same, except that D has nicer syntax. I don't think /class/ templates are confusing you at all! I think what's confusing you is that in D you can have /namespace/ templates, which don't exist in C++. Let me make an approximate C++ translation. Here's the D again: template A(T) { int x; } That is roughly equivalent to, in C++ namespace A_int { int x; } namespace A_float { int x; } namespace A_double { int x; } ...and so on for every imaginable type. Now it should be clear to you that A_int::x is a different variable from A_float::x, yes? For a namespaces to be "instantiated" just means that the corresponding chunk of code is there. To be /not/ instantiated would mean that it isn't there - which is just as well really, because there are in infinite number of possible types! To instantiate a namespace template, you only have to refer to it. I doesn't matter how. Clear? | |||
February 10, 2008 Re: Question about explicit template instantiation | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Edward Diener | Edward Diener さんは書きました: > Tyro[a.c.edwards] wrote: >> Edward Diener さんは書きました: [snip] > > I understand what a template is and that the instantiation of a template is a type ( class ). So in the example above 'a' and 'b' are aliases for types, ie. typedef in C++. Therefore the statements "a.f = 3;" and 'assert(b.f == 3);" made no sense to me. Actually, I said a "template is NOT a type." However, I don't tink I have enought experience in either English or D to explain thing to you so I'll stop before embarrasing myself further. > But I think I understand them now, but hopefully someone will clarify things for me. It seems in D one can instantiate a temporary object from a type which has a default constructor simply by using the type, whereas in C++ one must use the type followed by '()'. So whereas if X were a class with a default constructor with the data member Y, in C++ one would use 'X().Y' to access the temporary's Y data member while in D it appears one can use 'X.Y' to access the temporary's data member. Unfortunately I don't think you undersand... see previous comment. > What I quoted in my OP was all directly from the documentation, not anything I made up. Somehow you think that the lines: > > a.f = 3; > assert(b.f == 3); // a and b refer to the same instance of TFoo > > were inserted by me. No ! They were in the doc and they appeared to be incorrect, and I wanted an explanation for them. No, actually I went to the document that you were reading, read a little further down the page and took an example of a CLASS template and used it to attempt an explanation. Hopefully, someone will be able to assist you. Good luck! Andrew | |||
February 10, 2008 Re: Question about explicit template instantiation | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Janice Caron | Janice Caron wrote: > On 10/02/2008, Edward Diener <eddielee_no_spam_here@tropicsoft.com> wrote: >>> template MyNamespace(T) >>> { >>> int x; >>> } > >> This is confusing to me coming from C++. In C++ instantiating a class >> template produces a type. Is that not the way D works ? > > That's /exactly/ the way that D works. With CLASS templates, D works > just like C++. No problem. Compare: c++ > > template<class T> class A > { > int x; > }; > > A<int> a1; > A<double> a2; > > and the D equivalent: > > class A(T) > { > int x; > } > > auto a1 = new A!(int); > auto a2 = new A!(double); > > They're exactly the same, except that D has nicer syntax. I don't > think /class/ templates are confusing you at all! I think what's > confusing you is that in D you can have /namespace/ templates, which > don't exist in C++. The explanation for Class Templates in the D1 doc does not explain anything at all. That is why I assumed the template A(T) notation referred to the equivalent of the C++ class template. > > Let me make an approximate C++ translation. Here's the D again: > > template A(T) > { > int x; > } > > That is roughly equivalent to, in C++ > > namespace A_int > { > int x; > } > > namespace A_float > { > int x; > } > > namespace A_double > { > int x; > } > > ...and so on for every imaginable type. Now it should be clear to you > that A_int::x is a different variable from A_float::x, yes? Now I understand. I was surely fooled by the doc. > > For a namespaces to be "instantiated" just means that the > corresponding chunk of code is there. To be /not/ instantiated would > mean that it isn't there - which is just as well really, because there > are in infinite number of possible types! > > To instantiate a namespace template, you only have to refer to it. I > doesn't matter how. > > Clear? I think so. Instantiating a namespace template merely puts the equivalent code, with the types you instantiate it with substituted each time those types are referred to in the namespace, directly into your source. I still do not understand what the object used for the instantiation is. In your example above what is: A!(int) ? Is it some kind of namespace ? Can I say: A!(int) x; ? If so, what is x ? | |||
Copyright © 1999-2021 by the D Language Foundation
Permalink
Reply