467,083 Members | 1,261 Online
Bytes | Developer Community
Ask Question

Home New Posts Topics Members FAQ

Post your question to a community of 467,083 developers. It's quick & easy.

Template name lookup

Hi,

I can compile the code below with GCC 3.4.2, because function g is a
"dependent name".

template<class T>
void f1(T t)
{
g(t);
}

void g(int i)
{

}

int main()
{
f1<int>(10);
return 0;
}

But if I change the function g to a template function, things became
different. I cannot pass the compilation with GCC 3.4.2, but it works
fine with Visual C/C++ 7.

template<class T>
void f1(T t)
{
g<0>(t);
}

template<int I>
void g(int i)
{

}

int main()
{
f1<int>(10);
return 0;
}

The error message from GCC is:
main.cpp: In function `void f1(T)':
main.cpp:23: error: `g' undeclared (first use this function)
main.cpp:23: error: (Each undeclared identifier is reported only once
for each function it appears in.)
main.cpp: At global scope:
main.cpp:28: error: `template<int I> void g(int)' used prior to
declaration

Why?

Thanks,

Phil

Jul 23 '05 #1
  • viewed: 1592
Share:
10 Replies
ph**********@yahoo.com wrote:
But if I change the function g to a template function, things became
different. I cannot pass the compilation with GCC 3.4.2, but it works
fine with Visual C/C++ 7.

template<class T>
void f1(T t)
{
g<0>(t);
}

template<int I>
void g(int i)
{

}

int main()
{
f1<int>(10);
return 0;
}

The error message from GCC is:
main.cpp: In function `void f1(T)':
main.cpp:23: error: `g' undeclared (first use this function)
main.cpp:23: error: (Each undeclared identifier is reported only once
for each function it appears in.)
main.cpp: At global scope:
main.cpp:28: error: `template<int I> void g(int)' used prior to
declaration

Why?

template<int I>
void g(int i)
{

}
template<class T>
void f1(T t)
{
g<0>(t);
}
int main()
{
f1<int>(10);
return 0;
}

--
Ioannis Vranos

http://www23.brinkster.com/noicys
Jul 23 '05 #2

<ph**********@yahoo.com> wrote in message
news:11**********************@g14g2000cwa.googlegr oups.com...
Hi,

I can compile the code below with GCC 3.4.2, because function g is a
"dependent name".

template<class T>
void f1(T t)
{
g(t);
}

void g(int i)
{

}

int main()
{
f1<int>(10);
return 0;
}

But if I change the function g to a template function, things became
different. I cannot pass the compilation with GCC 3.4.2, but it works
fine with Visual C/C++ 7.

template<class T>
void f1(T t)
{
g<0>(t);
}

template<int I>
void g(int i)
{

}

int main()
{
f1<int>(10);
return 0;
}

The error message from GCC is:
main.cpp: In function `void f1(T)':
main.cpp:23: error: `g' undeclared (first use this function)
main.cpp:23: error: (Each undeclared identifier is reported only once
for each function it appears in.)
main.cpp: At global scope:
main.cpp:28: error: `template<int I> void g(int)' used prior to
declaration

Why?


A first glance at your code suggested a problem with the GCCs template
instantiation model. The problem is that connected to the point of
instantiation and the order that templates are substituted. For a more
detailed description Id suggest for example "C++ templates" by David
Vandevoorde & Nicolai Josuttis.

Anyway, you can help yourself easily by putting the definition of g() before
f().

Cheers
Chris
Jul 23 '05 #3

Chris Theis wrote:
<ph**********@yahoo.com> wrote in message
news:11**********************@g14g2000cwa.googlegr oups.com...
Hi,

I can compile the code below with GCC 3.4.2, because function g is a "dependent name".

template<class T>
void f1(T t)
{
g(t);
}

void g(int i)
{

}

int main()
{
f1<int>(10);
return 0;
}

But if I change the function g to a template function, things became different. I cannot pass the compilation with GCC 3.4.2, but it works fine with Visual C/C++ 7.

template<class T>
void f1(T t)
{
g<0>(t);
}

template<int I>
void g(int i)
{

}

int main()
{
f1<int>(10);
return 0;
}

The error message from GCC is:
main.cpp: In function `void f1(T)':
main.cpp:23: error: `g' undeclared (first use this function)
main.cpp:23: error: (Each undeclared identifier is reported only once for each function it appears in.)
main.cpp: At global scope:
main.cpp:28: error: `template<int I> void g(int)' used prior to
declaration

Why?
A first glance at your code suggested a problem with the GCCs

template instantiation model.


I assume you meant "Visual C++" instead of "GCC" here?
GNU is correct in refusing the code (Visual C++ does not correctly
implement the standard here): You cannot use template arguments
after a name unless it is somehow known that the name denotes a
template.

During the first round of standardization of C++ it was briefly
considered to add new syntax for this very example, but ultimately
it was considered unnecessary. (Something like "template g<0>(t)".)

Daveed

Jul 23 '05 #4

<va*********@gmail.com> wrote in message instantiation model.

[SNIP]
I assume you meant "Visual C++" instead of "GCC" here?
GNU is correct in refusing the code (Visual C++ does not correctly
implement the standard here): You cannot use template arguments
after a name unless it is somehow known that the name denotes a
template. During the first round of standardization of C++ it was briefly
considered to add new syntax for this very example, but ultimately
it was considered unnecessary. (Something like "template g<0>(t)".)


Ooops, thanks for the correction Daveed. Do you happen to know how Visual
C++ treats the instantiation here, so that the unexpectedly code works?

Cheers
Chris
Jul 23 '05 #5

Chris Theis wrote:
[...]
Ooops, thanks for the correction Daveed. Do you happen to know how Visual C++ treats the instantiation here, so that the unexpectedly code

works?

The Microsoft compiler treats templates a bit like macros and basically
doesn't look at template definitions until instantiation time. (Hence
it
is unable to meet the standard 2-phase lookup requirements.) Instead,
it performs instantiation at the end of the translation unit and at
that
time it "replays" the tokens of the template definition with the
template
parameters substituted. In the example under discussion, this
replaying
for "f1<int>" happens after all the source (including the template "g")
has been seen, and therefore "g<0>" is resolved.

A consequence of doing things like this is that you can write
template<class T> void f() {
blah blah // literally, try it!
}

and the compiler will accept the code despite the nonsensical function
body (as long as you don't actually instantiate the template).

(I'm writing this not based on actual knowledge of the VC++ internals,
but based on the analysis of various cases and on knowing how some
other implementation historically worked in the same way.)

(The EDG compiler by default also accepts such example for backward
compatibility reasons. However, in its mode standard-conforming modes
if will issue an error.)

Daveed

Jul 23 '05 #6
va*********@gmail.com wrote:
The Microsoft compiler treats templates a bit like macros and basically
doesn't look at template definitions until instantiation time. (Hence
it
is unable to meet the standard 2-phase lookup requirements.) Instead,
it performs instantiation at the end of the translation unit and at
that
time it "replays" the tokens of the template definition with the
template
parameters substituted. In the example under discussion, this
replaying
for "f1<int>" happens after all the source (including the template "g")
has been seen, and therefore "g<0>" is resolved.

A consequence of doing things like this is that you can write
template<class T> void f() {
blah blah // literally, try it!
}

and the compiler will accept the code despite the nonsensical function
body (as long as you don't actually instantiate the template).

(I'm writing this not based on actual knowledge of the VC++ internals,
but based on the analysis of various cases and on knowing how some
other implementation historically worked in the same way.)

(The EDG compiler by default also accepts such example for backward
compatibility reasons. However, in its mode standard-conforming modes
if will issue an error.)

The above also compiles with Intel C++ 8.1 and VC++ 2005 February 2005 CTP.

Does the 2-phase lookup mean that the function name needs not "be
already in scope" as with the usual functions?

--
Ioannis Vranos

http://www23.brinkster.com/noicys
Jul 23 '05 #7

<va*********@gmail.com> wrote in message
news:11**********************@o13g2000cwo.googlegr oups.com...

Chris Theis wrote:
[...]
Ooops, thanks for the correction Daveed. Do you happen to know how

Visual
C++ treats the instantiation here, so that the unexpectedly code

works?

The Microsoft compiler treats templates a bit like macros and basically
doesn't look at template definitions until instantiation time. (Hence
it
is unable to meet the standard 2-phase lookup requirements.) Instead,
it performs instantiation at the end of the translation unit and at
that
time it "replays" the tokens of the template definition with the
template
parameters substituted. In the example under discussion, this
replaying
for "f1<int>" happens after all the source (including the template "g")
has been seen, and therefore "g<0>" is resolved.

A consequence of doing things like this is that you can write
template<class T> void f() {
blah blah // literally, try it!
}

and the compiler will accept the code despite the nonsensical function
body (as long as you don't actually instantiate the template).

(I'm writing this not based on actual knowledge of the VC++ internals,
but based on the analysis of various cases and on knowing how some
other implementation historically worked in the same way.)

(The EDG compiler by default also accepts such example for backward
compatibility reasons. However, in its mode standard-conforming modes
if will issue an error.)

Daveed


Thanks Daveed, that was very informative!

Chris
Jul 23 '05 #8

Ioannis Vranos wrote:
va*********@gmail.com wrote: [...]
A consequence of doing things like this is that you can write
template<class T> void f() {
blah blah // literally, try it!
}

[...] The above also compiles with Intel C++ 8.1 and VC++ 2005 February 2005 CTP.

(I believe the Intel compiler has a --strict option that will cause
it to use the standard rules.)
Does the 2-phase lookup mean that the function name needs not "be
already in scope" as with the usual functions?


Pretty much. The exception are dependent unqualified calls
with no explicit template arguments. They come in two
variants: (1) your plain function call ("f(x, y)" where x and/or
y is dependent), and (2) simple operator invocations ("x * y"
where x and/or y is dependent). These can still appear
without actually have the function or operator be visible in
the template definition.

Daveed

Jul 23 '05 #9
Thanks for all of the replies.

Phil

Jul 23 '05 #10
Following might be a solution if you have to deal with the case.

template<class P>
void f()
{
P::template get<0>();
}

class A
{
public:
template<int I>
static void get()
{
cout << "hi" << endl;
}
};
int main(int argc, char *argv[])
{
f<A>();
return 0;
}

Phil

Jul 23 '05 #11

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

2 posts views Thread by Brian | last post: by
7 posts views Thread by Hunter Hou | last post: by
8 posts views Thread by mattias.nissler@googlemail.com | last post: by
4 posts views Thread by Thomas.Zauner@icp.uni-stuttgart.de | last post: by
5 posts views Thread by Ian Collins | last post: by
10 posts views Thread by Unkown to Xnntp | last post: by
2 posts views Thread by puzzlecracker | last post: by
By using this site, you agree to our Privacy Policy and Terms of Use.