 |
C++Talk.NET C++ language newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
Matthias Hofmann Guest
|
Posted: Fri Jul 16, 2004 12:18 am Post subject: Some observations about template instantiation |
|
|
Hello!
I have recently become aware of certain curiosities related to template
instantiations. Consider, as an example, the following code:
// BEGIN CODE
#include <iostream>
using namespace std;
struct A {};
struct B
{
// An A is convertible to a B.
B( const A& a = A() ) {}
};
template <class T> void f( const T& r )
{
// Tell me who you are.
cout << typeid( r ).name() << endl;
}
int main()
{
// Instantiates "void f( const B& )".
f( B() );
// Instantiates "void f( const A& )", although
// "void f( const B& )" could be used.
f( A() );
return 0;
}
// END CODE
In the above example, the compiler instantiates to distinct functions for
struct A and struct B, although it could pass A to the function it
instantiated for B. However, you would have to force the compiler to that
that:
f
I guess that the standard prescribes that behaviour somewhere, and actually
this is not yet what I find curious. What indeed puzzled me was that the
whole matter changes when default parameters come into play:
template <class T> void f( const T& r = B() ) // Note the default parameter.
{
// Same as before.
}
int main()
{
// Error, cannot deduce template argument.
f();
return 0;
}
A few days ago someone has explained to me in another thread that this
behaviour is due to the reason that the default argument expression is valid
for any type T for which there is an implicit conversion from B to T. If I
do not want to pass the functional argument to f(), I have to pass it a
template argument:
f<B>();
The problem I got is that I do not see any difference between passing a
functional argument explicitly or using the default parameter, I think the
folowing to calls should be the same:
f( B() );
f(); // Default argument is B().
The first call is also "valid for any type T for which there is an implicit
conversion from B to T", but the compiler still decides for B. So what is
the rationale behind that?
Best regards,
Matthias Hofmann
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Tokyo Tomy Guest
|
Posted: Fri Jul 16, 2004 11:22 am Post subject: Re: Some observations about template instantiation |
|
|
"Matthias Hofmann" <hofmann (AT) anvil-soft (DOT) com> wrote
| Quote: | Hello!
I have recently become aware of certain curiosities related to template
instantiations. Consider, as an example, the following code:
// BEGIN CODE
#include <iostream
using namespace std;
struct A {};
struct B
{
// An A is convertible to a B.
B( const A& a = A() ) {}
};
template
{
// Tell me who you are.
cout << typeid( r ).name() << endl;
}
int main()
{
// Instantiates "void f( const B& )".
f( B() );
// Instantiates "void f( const A& )", although
// "void f( const B& )" could be used.
f( A() );
return 0;
}
// END CODE
In the above example, the compiler instantiates to distinct functions for
struct A and struct B, although it could pass A to the function it
instantiated for B. However, you would have to force the compiler to that
that:
f
I guess that the standard prescribes that behaviour somewhere, and actually
this is not yet what I find curious. What indeed puzzled me was that the
whole matter changes when default parameters come into play:
template <class T> void f( const T& r = B() ) // Note the default parameter.
{
// Same as before.
}
int main()
{
// Error, cannot deduce template argument.
f();
return 0;
}
A few days ago someone has explained to me in another thread that this
behaviour is due to the reason that the default argument expression is valid
for any type T for which there is an implicit conversion from B to T. If I
do not want to pass the functional argument to f(), I have to pass it a
template argument:
f<B>();
The problem I got is that I do not see any difference between passing a
functional argument explicitly or using the default parameter, I think the
folowing to calls should be the same:
f( B() );
f(); // Default argument is B().
The first call is also "valid for any type T for which there is an implicit
conversion from B to T", but the compiler still decides for B. So what is
the rationale behind that?
|
I think this is understandable.
The template function with default parameter needs the following two
steps.
1. Instantiate template function f(const T& r)
2. Assign default parameter B() to r
At the step 1 for instantiation, the complier must know the type of
r, but does not yet know, because the assignment (initialization) is
not yet executed.
However, you may still not understand why f(B())also works fine. So, I
add another step to the above procedure.
0. Try to find a type information from the parameter list
1. Instantiate template function f(const T& r)
2. Assign default parameter B() to r
(if the parameter is not supplied from the parameter list.)
This is only my hypothesis for more discussion. Welcome any objection.
Regards,
T Tomy
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Matthias Hofmann Guest
|
Posted: Sat Jul 17, 2004 10:11 am Post subject: Re: Some observations about template instantiation |
|
|
Tokyo Tomy <hosoda (AT) jtec (DOT) or.jp> schrieb in im Newsbeitrag:
[email]49c1da0b.0407160059.27162ff1 (AT) posting (DOT) google.com[/email]...
| Quote: | "Matthias Hofmann" <hofmann (AT) anvil-soft (DOT) com> wrote
|
[snip]
| Quote: |
I think this is understandable.
The template function with default parameter needs the following two
steps.
1. Instantiate template function f(const T& r)
2. Assign default parameter B() to r
At the step 1 for instantiation, the complier must know the type of
r, but does not yet know, because the assignment (initialization) is
not yet executed.
However, you may still not understand why f(B())also works fine. So, I
add another step to the above procedure.
0. Try to find a type information from the parameter list
1. Instantiate template function f(const T& r)
2. Assign default parameter B() to r
(if the parameter is not supplied from the parameter list.)
This is only my hypothesis for more discussion. Welcome any objection.
|
Your hypothesis sounds plausible. However, I expected the compiler to do the
following steps:
1. Try to find type information from the parameter list
2. If no arguments are passed, get type information from default parameters
3. Instantiate template function
4. Assign actual parameter to r if available, otherwise use default
parameter
I guess that the standard simply does not require the compiler to do these
steps. Instead, type information is only taken from the actual parameters or
from additional template arguments. It's not that I have a problem with it,
I was simply curious...
Best regards,
Matthias Hofmann
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Roshan Guest
|
Posted: Tue Jul 20, 2004 9:41 pm Post subject: Re: Some observations about template instantiation |
|
|
| Quote: | 1. Try to find type information from the parameter list
2. If no arguments are passed, get type information from default parameters
3. Instantiate template function
4. Assign actual parameter to r if available, otherwise use default
parameter
|
Parameter lists are not used for deducing types. Arguments lists are.
-Roshan
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
|