template instantiation error

H

Hunter Hou

Hello,

I'm trying one example of <<the C++ programming language>> Page 865

int f( int );
template< class T > T g( T t ) { return f( t ); }
char c = g( 'a' ); ************
char f( char );

Stroustrup said **** line is wrong because alternative resolution of f( t )
are possible.

But I used g++ in mingw to compile above code, there's nothing wrong. My
code is like this:



//template_study.cpp

int f( int );
template< class T > T g( T t ) { return f( t ); }
char c = g( 'a' );
char f( char );

int main() { return 0; }





Who would like to shed some light on me?

And who can explain further about template instantiation and namespace? I
don't quite understand what Stroustrup says.


Thanks,
Hunter
 
T

tom_usenet

Hello,

I'm trying one example of <<the C++ programming language>> Page 865

int f( int );
template< class T > T g( T t ) { return f( t ); }
char c = g( 'a' ); ************

The above would call int f(int) on a conforming compiler.
char f( char );

Stroustrup said **** line is wrong because alternative resolution of f( t )
are possible.

I doubt he said exactly that. He may have said something about
dependent name resolution?
But I used g++ in mingw to compile above code, there's nothing wrong.

You need g++ 3.4 (see www.mingw.org). This is the first GCC version to
include a partial implementation of two phase name lookup in
templates.
And who can explain further about template instantiation and namespace? I
don't quite understand what Stroustrup says.

int f( int );
The above declares a global function int f(int).

template< class T > T g( T t )
{
return f( t );
The name "f" used here is a dependent name - that is, the meaning of
it depends on the type of T. This means that lookup doesn't happen
immediately.

}

char c = g( 'a' );
Instead, lookup of the f in g is deferred until the point of
instantiation, here. Names "f" are looked up both at the point of
definition of g (where int f(int) is found), and at the point of
instantiation using argument dependent lookup (where again, int f(int)
is found, since char f(char) hasn't been declared yet). So the call to
g calls int f(int).

char f( char );
This function isn't called.

Note that GCC 3.4 still has some bugs with name lookup, so it will
call char f(char) even though it hasn't been declared at the point of
instantiation. I assume this will be fixed in GCC 3.5. However, a few
compilers do get your example right - notably Comeau C++ and other EDG
based compilers such as Intel C++ (they output a linker error for the
missing definition of int f(int) - GCC outputs a error for char
f(char) which is incorrect).

There is only one book that covers these name lookup issues in detail,
and that's Vandevoorde and Josuttis' book, "C++ Templates". Worth a
read (although I haven't read it myself).

Tom
 
M

Michiel Salters

Hunter Hou said:
Hello,

I'm trying one example of <<the C++ programming language>> Page 865

int f( int );
template< class T > T g( T t ) { return f( t ); }
char c = g( 'a' ); ************
char f( char );

Stroustrup said **** line is wrong because alternative resolution of f( t )
are possible.

Are you sure the example wasn't

int f( int );
template< class T > T g( T t ) { return f( t ); }
char f( char );
char c = g( 'a' ); ************


The problem with this code is that f(t) depends on the meaning of t.
This meaning changes between the definition of g<T> and the call
g<char>('a'). Initially , the name f refers to the single function
f(int), but later it refers to the overload set f(int) and f(char).

Don't change the meaning of names in templates between the template
definition and the template usage, unless you have a very good book
or understand chapter 14 of the C++ standard.

Regards,
Michiel Salters
 
N

New_user

I'm trying one example of said:
int f( int );
template< class T > T g( T t ) { return f( t ); }
char c = g( 'a' ); ************
char f( char );

Stroustrup said **** line is wrong because alternative resolution of f( t )
are possible.

I don't remember Bjarne's words exactly. But this example compilable.
"Error" is: f(int) will be called, no fun(char): it's so-named two
phase name-lookup (I don't have mingw, but if he calls f(char) == he
does not know rules :).

For example, my icc calls fun(int).
 
T

tom_usenet

The above would call int f(int) on a conforming compiler.


I doubt he said exactly that. He may have said something about
dependent name resolution?

Ok, I take back my earlier answer. The code in fact is well-formed,
but has undefined behaviour. Since the call to "f" has a better match
if all extern functions are considered than it does it you only take
ones found in the instantiation context (i.e. f(char) is a better
match than f(int), but isn't visible at the instantiation point), the
call to f is undefined.

Apologies to Stroustrup and to GCC 3.4, which doesn't have a bug after
all.

(See 14.6.4.2 in the standard)

Tom
 
H

Hunter Hou

Ok, I take back my earlier answer. The code in fact is well-formed,
but has undefined behaviour. Since the call to "f" has a better match
if all extern functions are considered than it does it you only take
ones found in the instantiation context (i.e. f(char) is a better
match than f(int), but isn't visible at the instantiation point), the
call to f is undefined.



Stroustrup says

We could generate the specialization g<char>(char) at the point of
instantiation and get f(int) called. Alternatively, we could wait and
generate the specialization at the end of the translation unit and get
f(char) called. Consequently, the call g('a') is an error.
 
T

tom_usenet

I don't remember Bjarne's words exactly. But this example compilable.
"Error" is: f(int) will be called, no fun(char): it's so-named two
phase name-lookup (I don't have mingw, but if he calls f(char) == he
does not know rules :).

For example, my icc calls fun(int).

The code has undefined behaviour - f(char) or f(int) might be called,
or neither.

Tom
 
T

tom_usenet

Stroustrup says

We could generate the specialization g<char>(char) at the point of
instantiation and get f(int) called. Alternatively, we could wait and
generate the specialization at the end of the translation unit and get
f(char) called. Consequently, the call g('a') is an error.

That sounds right. Which bit don't you understand? Do you understand
"dependent names"? "Argument dependent lookup"? "Implicit template
instantiation and point of instantiation"? Those are the mechanisms
that are involved here.

Tom
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,170
Messages
2,570,925
Members
47,464
Latest member
Bobbylenly

Latest Threads

Top