February 10, 2008 Re: Question about explicit template instantiation | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Edward Diener | Edward Diener:
> Thanks for the information but I await your and Janice's response about what a template instantiation is.
The situation is rather simple. A D template is a section of code that is parametric in one or more types. Just like a function is a piece of code that is parametric on the value of some types (the situation isn't fully symmetric because in D types aren't first class values yet, but they are close enough for many purposes). Inside that section you can put what you want, types that depend of the template types, classes that are depends of the template types (that you can think as variables), etc. When you instantiate a type you give the value to those type variables, so you just define what types those "type variables" are, so you define real pieces of code, for functions, classes, etc, that you can take a pointer of, you can instantiate, you can call, etc. Before that, they are "virtual", generic, not even fully cheeked by the compiler. As time passes, D types become a bit more and more first class, that allows you to operate on them in more ways (at compile time).
Bye,
bearophile
| |||
February 10, 2008 Re: Question about explicit template instantiation | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Edward Diener | On Sun, 10 Feb 2008 17:31:36 -0500, Edward Diener wrote:
> 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 ?
Well, you can't write A!(int) x; unless you precede it with alias.
If we have:
template A(T) { T f; }
I'm new to templates so I don't really know how to say what A!(int) is, but I think a good way to think of it as declaring an instance of a struct.
struct B { int f };
where B = A!(int);
| |||
February 10, 2008 Re: Question about explicit template instantiation | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Jesse Phillips | On Sun, 10 Feb 2008 22:58:51 +0000, Jesse Phillips wrote:
> On Sun, 10 Feb 2008 17:31:36 -0500, Edward Diener wrote:
>
>> 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 ?
>
> Well, you can't write A!(int) x; unless you precede it with alias.
>
> If we have:
>
> template A(T) { T f; }
>
> I'm new to templates so I don't really know how to say what A!(int) is, but I think a good way to think of it as declaring an instance of a struct.
>
> struct B { int f };
>
> where B = A!(int);
Hold on I just made a type out of A!(int) so
A!(int) would be equivalent to
struct B { int f };
B a;
where B a is A!(int);
| |||
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: > 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 ? Yes. It is exactly a namespace. > Can I say: > > A!(int) x; > > ? Sometimes, but only in special case. If you don't specify a member of the namespace, then the compiler will /assume/ a member whose name is the same as that of the template. So, if we have: template A(T) { int A; } then A!(int) x; would be shorthand for A!(int).A x; But if there wasn't an A in the namespace, then it wouldn't compile. That little "trick" is really, really useful, because it can make for a lot less typing. So - in general - A!(T) with no member, is the same thing as A!(T).A, if A!(T).A exists. /What/ is it, depends. It's whatever A!(T).A is. | |||
February 10, 2008 Re: Question about explicit template instantiation | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Jesse Phillips | On 10/02/2008, Jesse Phillips <jessekphillips@gmail.com> wrote:
> Well, you can't write A!(int) x; unless you precede it with alias.
Not so.
template A(T)
{
int A;
}
A!(double) = 42;
writefln(A!(double)); // prints 42
writefln(typeof(A!(double))); // prints double
In this example, A!(double) is short for A!(double).A, which in an
int, so we can assign a value to it and print it.
But
template A(T)
{
struct A
{
int x;
}
}
In /this/ example A!(T).A is a type. (And hence, so is A!(T)). Observe
that there's a neater way of writing that though. We can abbreviate
that to
struct A(T)
{
int x;
}
| |||
February 10, 2008 Re: Question about explicit template instantiation | ||||
|---|---|---|---|---|
| ||||
On 10/02/2008, Janice Caron <caron800@googlemail.com> wrote:
> On 10/02/2008, Jesse Phillips <jessekphillips@gmail.com> wrote:
> > Well, you can't write A!(int) x; unless you precede it with alias.
>
> Not so.
>
> template A(T)
> {
> int A;
> }
>
> A!(double) = 42;
> writefln(A!(double)); // prints 42
> writefln(typeof(A!(double))); // prints double
Whoa! Big mistake! Sorry. Typo. Got that wrong. Don't want to confuse anyone! Let's try again...
writefln(typeof(A!(double))); // prints int
That's better!
Phew!
| ||||
February 11, 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:fonlr1$2krb$1@digitalmars.com... > 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 ? As Janice said, instantiating a template creates a namespace in which the template parameters are replaced by the arguments given in the instantiation. C++'s templates are intrinsically bound to either classes or functions, and instantiating a template in C++ gets you either a class or a function. D's templates are more general; they simply declare a namespace in which one or more declarations can exist, all parameterized by the template's parameters. It might help to know that this: class A(T) { .. } is _exactly_ equivalent (and in fact turned into this by the compiler) to: template A(T) { class A { ... } } Why this works is because if a template contains exactly one declaration, and that declaration has the same name as the template, referring to the template instantiation refers to the symbol inside it. So: A!(int).A a; A!(int) b; // sugar for the previous line Function templates work similarly. void foo(T)() { ... } == template foo(T) { void foo() { } } So this function can be called either as foo!(int)() or as foo!(int).foo(). This extends to any kind of declaration. template A(T, U) { T t; U u; } template A(T) { // an alias is a declaration too. alias A!(T, T) A; } alias A!(int, float) one; // one.t is int, one.u is float // we don't have to say A!(char).A alias A!(char) two; // both two.t and two.u are char You can have more than one declaration in a template, but then the "automatic symbol use" magic stops happening. | |||
February 11, 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:
>> 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 ?
>
> Yes. It is exactly a namespace.
>
>
>
>> Can I say:
>>
>> A!(int) x;
>>
>> ?
>
> Sometimes, but only in special case. If you don't specify a member of
> the namespace, then the compiler will /assume/ a member whose name is
> the same as that of the template. So, if we have:
>
> template A(T)
> {
> int A;
> }
>
> then
>
> A!(int) x;
>
> would be shorthand for
>
> A!(int).A x;
>
> But if there wasn't an A in the namespace, then it wouldn't compile.
> That little "trick" is really, really useful, because it can make for
> a lot less typing. So - in general - A!(T) with no member, is the same
> thing as A!(T).A, if A!(T).A exists.
>
> /What/ is it, depends. It's whatever A!(T).A is.
Thanks for the explanation !
| |||
February 11, 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:fonlr1$2krb$1@digitalmars.com...
>
>> 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 ?
>
> As Janice said, instantiating a template creates a namespace in which the template parameters are replaced by the arguments given in the instantiation.
>
> C++'s templates are intrinsically bound to either classes or functions, and instantiating a template in C++ gets you either a class or a function.
>
> D's templates are more general; they simply declare a namespace in which one or more declarations can exist, all parameterized by the template's parameters.
>
> It might help to know that this:
>
> class A(T)
> {
> ..
> }
>
> is _exactly_ equivalent (and in fact turned into this by the compiler) to:
>
> template A(T)
> {
> class A
> {
> ...
> }
> }
>
> Why this works is because if a template contains exactly one declaration, and that declaration has the same name as the template, referring to the template instantiation refers to the symbol inside it. So:
>
> A!(int).A a;
> A!(int) b; // sugar for the previous line
>
> Function templates work similarly.
>
> void foo(T)()
> {
> ...
> }
>
> ==
>
> template foo(T)
> {
> void foo()
> {
>
> }
> }
>
> So this function can be called either as foo!(int)() or as foo!(int).foo().
>
> This extends to any kind of declaration.
>
> template A(T, U)
> {
> T t;
> U u;
> }
>
> template A(T)
> {
> // an alias is a declaration too.
> alias A!(T, T) A;
> }
>
> alias A!(int, float) one; // one.t is int, one.u is float
>
> // we don't have to say A!(char).A
> alias A!(char) two; // both two.t and two.u are char
>
> You can have more than one declaration in a template, but then the "automatic symbol use" magic stops happening.
Thanks for the explanation !
| |||
Copyright © 1999-2021 by the D Language Foundation
Permalink
Reply