473,749 Members | 2,660 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Two-Phase lookup

Hi,

I've just had my first encounter with two-phase lookup and I'm
scratching my head a bit. The idea behind two phase look up is pretty
easy to understand, but I have a case that fails to compile although
it appears to me that it should.

template<typena me TYPE>
void
foo( std::map< int, TYPE pmap )
{
std::map< int, TYPE >::iterator iter ;
}

When compiled with g++ 4.0.2 gives the following error:

test.cc: In function 'void foo(std::map<in t, TYPE, std::less<int>,
std::allocator< std::pair<const int, TYPE >)':
test.cc:31: error: expected `;' before 'iter'
test.cc: In function 'void foo(std::map<in t, TYPE, std::less<int>,
std::allocator< std::pair<const int, TYPE >) [with TYPE = char]':
test.cc:42: instantiated from here
test.cc:31: error: dependent-name
'std::map<int,T YPE,std::less<i nt>,std::alloca tor<std::pair<c onst int,
TYPE >::iterator' is parsed as a non-type, but instantiation yields
a type
test.cc:31: note: say 'typename
std::map<int,TY PE,std::less<in t>,std::allocat or<std::pair<co nst int,
TYPE >::iterator' if a type is meant

Unless I'm mistaken, this should be a dependant name lookup, and thus
not be looked up until template instantiation.

According to this article:
http://www.codeproject.com/cpp/TwoPh...&select=949325

It should be dependant because its type is dependant. Which makes a
great deal of sense.

Given all that, what's causing this 'parsed as non-type' error?

This is purely an academic question, but its something I can't figure
out.

Thanks,
Paul Davis

Feb 8 '07 #1
13 5601
On 2/7/07 3:56 PM, in article
11************* ********@v45g20 00...legro ups.com,
"pa************ ***@gmail.com" <pa************ ***@gmail.comwr ote:
>
I've just had my first encounter with two-phase lookup and I'm
scratching my head a bit. The idea behind two phase look up is pretty
easy to understand, but I have a case that fails to compile although
it appears to me that it should.

template<typena me TYPE>
void
foo( std::map< int, TYPE pmap )
{
std::map< int, TYPE >::iterator iter ;
}

When compiled with g++ 4.0.2 gives the following error:

test.cc: In function 'void foo(std::map<in t, TYPE, std::less<int>,
test.cc:31: error: expected `;' before 'iter'

Unless I'm mistaken, this should be a dependant name lookup, and thus
not be looked up until template instantiation.
The compiler performs "two phase" name-lookup within the definition of a
class template, a nested class of a class template, a member of a class
template, or a member of a nested class of a class template - but not within
a function template like foo() in the example above.

Greg

Feb 8 '07 #2
On 8 Feb., 03:33, Greg Herlihy <gre...@pacbell .netwrote:
On 2/7/07 3:56 PM, in article
1170892566.0949 77.95...@v45g20 00cwv.googlegro ups.com,

"paul.joseph.da ...@gmail.com" <paul.joseph.da ...@gmail.comwr ote:
I've just had my first encounter with two-phase lookup and I'm
scratching my head a bit. The idea behind two phase look up is pretty
easy to understand, but I have a case that fails to compile although
it appears to me that it should.
template<typena me TYPE>
void
foo( std::map< int, TYPE pmap )
{
std::map< int, TYPE >::iterator iter ;
}
When compiled with g++ 4.0.2 gives the following error:
test.cc: In function 'void foo(std::map<in t, TYPE, std::less<int>,
test.cc:31: error: expected `;' before 'iter'
Unless I'm mistaken, this should be a dependant name lookup, and thus
not be looked up until template instantiation.

The compiler performs "two phase" name-lookup within the definition of a
class template, a nested class of a class template, a member of a class
template, or a member of a nested class of a class template - but not within
a function template like foo() in the example above.

Greg- Zitierten Text ausblenden -

- Zitierten Text anzeigen -
Greg Herlihy <gre...@pacbell .netwrote:
foo( std::map< int, TYPE pmap )
{
std::map< int, TYPE >::iterator iter ;
}
visual studi 2005 accepts your code,
for gcc add typename
e.g.:
typename std::map< int, TYPE >::iterator iter ;
lg Rudi

Feb 8 '07 #3
pa************* **@gmail.com wrote:
Hi,

I've just had my first encounter with two-phase lookup and I'm
scratching my head a bit. The idea behind two phase look up is pretty
easy to understand, but I have a case that fails to compile although
it appears to me that it should.

template<typena me TYPE>
void
foo( std::map< int, TYPE pmap )
{
std::map< int, TYPE >::iterator iter ;
}

When compiled with g++ 4.0.2 gives the following error:

test.cc: In function 'void foo(std::map<in t, TYPE, std::less<int>,
std::allocator< std::pair<const int, TYPE >)':
test.cc:31: error: expected `;' before 'iter'
test.cc: In function 'void foo(std::map<in t, TYPE, std::less<int>,
std::allocator< std::pair<const int, TYPE >) [with TYPE = char]':
test.cc:42: instantiated from here
test.cc:31: error: dependent-name
'std::map<int,T YPE,std::less<i nt>,std::alloca tor<std::pair<c onst int,
TYPE >::iterator' is parsed as a non-type, but instantiation yields
a type
test.cc:31: note: say 'typename
std::map<int,TY PE,std::less<in t>,std::allocat or<std::pair<co nst int,
TYPE >::iterator' if a type is meant

Unless I'm mistaken, this should be a dependant name lookup, and thus
not be looked up until template instantiation.

According to this article:
http://www.codeproject.com/cpp/TwoPh...&select=949325

It should be dependant because its type is dependant. Which makes a
great deal of sense.

Given all that, what's causing this 'parsed as non-type' error?

This is purely an academic question, but its something I can't figure
out.

Thanks,
Paul Davis
IMHO, I do not think this is a symptom of Two-Phase Lookup. I think this
is how the C++ parser think something is but turns out not to be.
What do I mean about this probably best described by an example.

class A
{
public:
typedef int someType;
static int someVariable;
}

Now let us look at this code (without any context)

A::someType
A::someVariable

It seems to be quite clear that A::SomethingGoe sHere could
either be a type or a variable (and even a function too!!)

So when the compiler first reads this part of the line:

std::map< int, TYPE >::iterator

The first thing, the parse assumes is "Hmmmmm
std::map<int,TY PE>::iterator must be a member variable!!"
(technically, it is a non-type: member variable or function)
which obviously is not. But natually, when the template gets
instantiated, it proves to be fatal!! what it originally assumed
was supposed to be a non-type is used as a type and in addition,
the instantiation process revealed it to be a type. OMG What
will Mr. Compiler do?!

So how do we correct this? Well actually, you compiler tells
you how to correct it!!
test.cc:31: note: say 'typename
std::map<int,TY PE,std::less<in t>,std::allocat or<std::pair<co nst int,
TYPE >::iterator' if a type is meant
This means, you should do this:
template<typena me TYPE>
void
foo( std::map< int, TYPE &pmap )
{
typename std::map< int, TYPE >::iterator iter ;
}

BTW, I added a reference to your pmap input :)

I hope that helped. :)

Good Luck!
Feb 8 '07 #4
On Feb 8, 1:26 am, Piyo <cybermax...@ya hoo.comwrote:
paul.joseph.da. ..@gmail.com wrote:
Hi,
I've just had my first encounter with two-phase lookup and I'm
scratching my head a bit. The idea behind two phase look up is pretty
easy to understand, but I have a case that fails to compile although
it appears to me that it should.
template<typena me TYPE>
void
foo( std::map< int, TYPE pmap )
{
std::map< int, TYPE >::iterator iter ;
}
When compiled with g++ 4.0.2 gives the following error:
test.cc: In function 'void foo(std::map<in t, TYPE, std::less<int>,
std::allocator< std::pair<const int, TYPE >)':
test.cc:31: error: expected `;' before 'iter'
test.cc: In function 'void foo(std::map<in t, TYPE, std::less<int>,
std::allocator< std::pair<const int, TYPE >) [with TYPE = char]':
test.cc:42: instantiated from here
test.cc:31: error: dependent-name
'std::map<int,T YPE,std::less<i nt>,std::alloca tor<std::pair<c onst int,
TYPE >::iterator' is parsed as a non-type, but instantiation yields
a type
test.cc:31: note: say 'typename
std::map<int,TY PE,std::less<in t>,std::allocat or<std::pair<co nst int,
TYPE >::iterator' if a type is meant
Unless I'm mistaken, this should be a dependant name lookup, and thus
not be looked up until template instantiation.
According to this article:
http://www.codeproject.com/cpp/TwoPh...0&forumid=1154...
It should be dependant because its type is dependant. Which makes a
great deal of sense.
Given all that, what's causing this 'parsed as non-type' error?
This is purely an academic question, but its something I can't figure
out.
Thanks,
Paul Davis

IMHO, I do not think this is a symptom of Two-Phase Lookup. I think this
is how the C++ parser think something is but turns out not to be.
What do I mean about this probably best described by an example.

class A
{
public:
typedef int someType;
static int someVariable;

}

Now let us look at this code (without any context)

A::someType
A::someVariable

It seems to be quite clear that A::SomethingGoe sHere could
either be a type or a variable (and even a function too!!)

So when the compiler first reads this part of the line:

std::map< int, TYPE >::iterator

The first thing, the parse assumes is "Hmmmmm
std::map<int,TY PE>::iterator must be a member variable!!"
(technically, it is a non-type: member variable or function)
which obviously is not. But natually, when the template gets
instantiated, it proves to be fatal!! what it originally assumed
was supposed to be a non-type is used as a type and in addition,
the instantiation process revealed it to be a type. OMG What
will Mr. Compiler do?!

So how do we correct this? Well actually, you compiler tells
you how to correct it!!
test.cc:31: note: say 'typename
std::map<int,TY PE,std::less<in t>,std::allocat or<std::pair<co nst int,
TYPE >::iterator' if a type is meant

This means, you should do this:
template<typena me TYPE>
void
foo( std::map< int, TYPE &pmap )
{
typename std::map< int, TYPE >::iterator iter ;

}

BTW, I added a reference to your pmap input :)

I hope that helped. :)

Good Luck!
Hi,

The compiler message is pretty straightforward about adding typename
to get the compilation to work. The question here is what about the
language is making this happen.

I've just found some interesting stuff in Stroustrup's "The C++
Programming Language 3rd Ed." in sections C.13.5 and C.13.8
>From C.13.5 (page 857 first paragraph of text in my copy) I quote:
"Naturally, a compiler could postpone all checking until
instantiation time where all information is avialable and could then
accept such examples. Howerver, that would be a standard language
extension."

On the next page, Stroustrup says, "The resolution is simple: unless
otherwise stated, an identifier is assumed to refer to something that
is not a type or a template."

Here's another concrete example:

#include <iostream>
#include <map>

template<typena me T1>
class A
{
public:
typedef T1 mem_type ;

T1 x ;
} ;

template<typena me T2>
void
foo( T2& var )
{
bar( var.x ) ; //This call compiles because of two-phase
construction.
//var.x is type-dependant, thus, its lookup is
delayed
//until template instantiation.

T2::mem_type val ; //This line is *not* affected by two-phase
lookup.
//Why not?
}

void
bar( int x )
{
std::cerr << x << std::endl ;
}

int
main( int argc, char* argv[] )
{
A<inta ;
a.x = 1 ;
foo( a ) ;
}

Does this mean that two-phase lookup applies only to function calls
and not variable instantiations? Judging from the second quote from
Stroustrup and this example, I'm guessing this is the case.

Thanks,
Paul

Feb 8 '07 #5
On Feb 7, 8:33 pm, Greg Herlihy <gre...@pacbell .netwrote:
On 2/7/07 3:56 PM, in article
1170892566.0949 77.95...@v45g20 00cwv.googlegro ups.com,

"paul.joseph.da ...@gmail.com" <paul.joseph.da ...@gmail.comwr ote:
I've just had my first encounter with two-phase lookup and I'm
scratching my head a bit. The idea behind two phase look up is pretty
easy to understand, but I have a case that fails to compile although
it appears to me that it should.
template<typena me TYPE>
void
foo( std::map< int, TYPE pmap )
{
std::map< int, TYPE >::iterator iter ;
}
When compiled with g++ 4.0.2 gives the following error:
test.cc: In function 'void foo(std::map<in t, TYPE, std::less<int>,
test.cc:31: error: expected `;' before 'iter'
Unless I'm mistaken, this should be a dependant name lookup, and thus
not be looked up until template instantiation.

The compiler performs "two phase" name-lookup within the definition of a
class template, a nested class of a class template, a member of a class
template, or a member of a nested class of a class template - but not within
a function template like foo() in the example above.

Greg
Greg,

This isn't quite correct. I've already posted an example that shows
otherwise. The question though is whether or not two-phase lookup
applies only to function calls vs. variable instantiations.

Paul

Feb 8 '07 #6
pa************* **@gmail.com wrote:
On Feb 8, 1:26 am, Piyo <cybermax...@ya hoo.comwrote:
>paul.joseph.da ...@gmail.com wrote:
>>Hi,
I've just had my first encounter with two-phase lookup and I'm
scratching my head a bit. The idea behind two phase look up is pretty
easy to understand, but I have a case that fails to compile although
it appears to me that it should.
template<type name TYPE>
void
foo( std::map< int, TYPE pmap )
{
std::map< int, TYPE >::iterator iter ;
}
When compiled with g++ 4.0.2 gives the following error:
test.cc: In function 'void foo(std::map<in t, TYPE, std::less<int>,
std::allocato r<std::pair<con st int, TYPE >)':
test.cc:31: error: expected `;' before 'iter'
test.cc: In function 'void foo(std::map<in t, TYPE, std::less<int>,
std::allocato r<std::pair<con st int, TYPE >) [with TYPE = char]':
test.cc:42: instantiated from here
test.cc:31: error: dependent-name
'std::map<int ,TYPE,std::less <int>,std::allo cator<std::pair <const int,
TYPE >::iterator' is parsed as a non-type, but instantiation yields
a type
test.cc:31: note: say 'typename
std::map<int, TYPE,std::less< int>,std::alloc ator<std::pair< const int,
TYPE >::iterator' if a type is meant
Unless I'm mistaken, this should be a dependant name lookup, and thus
not be looked up until template instantiation.
According to this article:
http://www.codeproject.com/cpp/TwoPh...0&forumid=1154...
It should be dependant because its type is dependant. Which makes a
great deal of sense.
Given all that, what's causing this 'parsed as non-type' error?
This is purely an academic question, but its something I can't figure
out.
Thanks,
Paul Davis
IMHO, I do not think this is a symptom of Two-Phase Lookup. I think this
is how the C++ parser think something is but turns out not to be.
What do I mean about this probably best described by an example.

class A
{
public:
typedef int someType;
static int someVariable;

}

Now let us look at this code (without any context)

A::someType
A::someVariabl e

It seems to be quite clear that A::SomethingGoe sHere could
either be a type or a variable (and even a function too!!)

So when the compiler first reads this part of the line:

std::map< int, TYPE >::iterator

The first thing, the parse assumes is "Hmmmmm
std::map<int,T YPE>::iterator must be a member variable!!"
(technically , it is a non-type: member variable or function)
which obviously is not. But natually, when the template gets
instantiated , it proves to be fatal!! what it originally assumed
was supposed to be a non-type is used as a type and in addition,
the instantiation process revealed it to be a type. OMG What
will Mr. Compiler do?!

So how do we correct this? Well actually, you compiler tells
you how to correct it!!
> test.cc:31: note: say 'typename
std::map<int,TY PE,std::less<in t>,std::allocat or<std::pair<co nst int,
TYPE >::iterator' if a type is meant

This means, you should do this:
template<typen ame TYPE>
void
foo( std::map< int, TYPE &pmap )
{
typename std::map< int, TYPE >::iterator iter ;

}

BTW, I added a reference to your pmap input :)

I hope that helped. :)

Good Luck!

Hi,

The compiler message is pretty straightforward about adding typename
to get the compilation to work. The question here is what about the
language is making this happen.

I've just found some interesting stuff in Stroustrup's "The C++
Programming Language 3rd Ed." in sections C.13.5 and C.13.8
>>From C.13.5 (page 857 first paragraph of text in my copy) I quote:
"Naturally, a compiler could postpone all checking until
instantiation time where all information is avialable and could then
accept such examples. Howerver, that would be a standard language
extension."

On the next page, Stroustrup says, "The resolution is simple: unless
otherwise stated, an identifier is assumed to refer to something that
is not a type or a template."

Here's another concrete example:

#include <iostream>
#include <map>

template<typena me T1>
class A
{
public:
typedef T1 mem_type ;

T1 x ;
} ;

template<typena me T2>
void
foo( T2& var )
{
bar( var.x ) ; //This call compiles because of two-phase
construction.
//var.x is type-dependant, thus, its lookup is
delayed
//until template instantiation.

T2::mem_type val ; //This line is *not* affected by two-phase
lookup.
//Why not?
}

void
bar( int x )
{
std::cerr << x << std::endl ;
}

int
main( int argc, char* argv[] )
{
A<inta ;
a.x = 1 ;
foo( a ) ;
}

Does this mean that two-phase lookup applies only to function calls
and not variable instantiations? Judging from the second quote from
Stroustrup and this example, I'm guessing this is the case.

Thanks,
Paul
Interesting point. I do think that both are dependent names and will
require a two-phase lookup to resolve what function (bar -bar(int)) or
type (T2::mem_type -int) should be used.

I will need to check my copy of Stroustrup's book to see in what context
he mentions this to figure out what to make of it. I believe that he is
saying that if a dependent name is first encountered (first pass) the
compiler will assume it is a non-type.

This means:

T2::mem_type at the first pass will be assumed to be a variable or a
function (aka non-type). On the other hand, bar() on the first pass is
correctly parsed as a function, we just don't know which one.

On the second pass, when all templates have been instantiated, it is
clear to the compiler that T2::mem_type is a type but the parse tree for
a type has already been generated and it flags it as an error (for GNU
and is probably "fixed on the fly" by Microsoft). bar() on the other
hand does some Koenig lookups and finds bar(int) satisfies the call.

BTW, you need to get into the habit of using typename in your examples
since, you bring up a valid question, does two-phase lookup occur on a
type but the compiler is complaining about a different thing: it is
confused as to whether or not the dependent name is a type or a
non-type. Which is why people reply to your post to simply add typename.

Hope that helps!
Feb 8 '07 #7
On Feb 8, 12:23 pm, Clint Chua <cybermax...@ya hoo.comwrote:
paul.joseph.da. ..@gmail.com wrote:
On Feb 8, 1:26 am, Piyo <cybermax...@ya hoo.comwrote:
paul.joseph.da. ..@gmail.com wrote:
Hi,
I've just had my first encounter with two-phase lookup and I'm
scratching my head a bit. The idea behind two phase look up is pretty
easy to understand, but I have a case that fails to compile although
it appears to me that it should.
template<typen ame TYPE>
void
foo( std::map< int, TYPE pmap )
{
std::map< int, TYPE >::iterator iter ;
}
When compiled with g++ 4.0.2 gives the following error:
test.cc: In function 'void foo(std::map<in t, TYPE, std::less<int>,
std::allocator <std::pair<cons t int, TYPE >)':
test.cc:31: error: expected `;' before 'iter'
test.cc: In function 'void foo(std::map<in t, TYPE, std::less<int>,
std::allocator <std::pair<cons t int, TYPE >) [with TYPE = char]':
test.cc:42: instantiated from here
test.cc:31: error: dependent-name
'std::map<int, TYPE,std::less< int>,std::alloc ator<std::pair< const int,
TYPE >::iterator' is parsed as a non-type, but instantiation yields
a type
test.cc:31: note: say 'typename
std::map<int,T YPE,std::less<i nt>,std::alloca tor<std::pair<c onst int,
TYPE >::iterator' if a type is meant
Unless I'm mistaken, this should be a dependant name lookup, and thus
not be looked up until template instantiation.
According to this article:
http://www.codeproject.com/cpp/TwoPh...0&forumid=1154...
It should be dependant because its type is dependant. Which makes a
great deal of sense.
Given all that, what's causing this 'parsed as non-type' error?
This is purely an academic question, but its something I can't figure
out.
Thanks,
Paul Davis
IMHO, I do not think this is a symptom of Two-Phase Lookup. I think this
is how the C++ parser think something is but turns out not to be.
What do I mean about this probably best described by an example.
class A
{
public:
typedef int someType;
static int someVariable;
}
Now let us look at this code (without any context)
A::someType
A::someVariable
It seems to be quite clear that A::SomethingGoe sHere could
either be a type or a variable (and even a function too!!)
So when the compiler first reads this part of the line:
std::map< int, TYPE >::iterator
The first thing, the parse assumes is "Hmmmmm
std::map<int,TY PE>::iterator must be a member variable!!"
(technically, it is a non-type: member variable or function)
which obviously is not. But natually, when the template gets
instantiated, it proves to be fatal!! what it originally assumed
was supposed to be a non-type is used as a type and in addition,
the instantiation process revealed it to be a type. OMG What
will Mr. Compiler do?!
So how do we correct this? Well actually, you compiler tells
you how to correct it!!
test.cc:31: note: say 'typename
std::map<int,TY PE,std::less<in t>,std::allocat or<std::pair<co nst int,
TYPE >::iterator' if a type is meant
This means, you should do this:
template<typena me TYPE>
void
foo( std::map< int, TYPE &pmap )
{
typename std::map< int, TYPE >::iterator iter ;
}
BTW, I added a reference to your pmap input :)
I hope that helped. :)
Good Luck!
Hi,
The compiler message is pretty straightforward about adding typename
to get the compilation to work. The question here is what about the
language is making this happen.
I've just found some interesting stuff in Stroustrup's "The C++
Programming Language 3rd Ed." in sections C.13.5 and C.13.8
>From C.13.5 (page 857 first paragraph of text in my copy) I quote:
"Naturally, a compiler could postpone all checking until
instantiation time where all information is avialable and could then
accept such examples. Howerver, that would be a standard language
extension."
On the next page, Stroustrup says, "The resolution is simple: unless
otherwise stated, an identifier is assumed to refer to something that
is not a type or a template."
Here's another concrete example:
#include <iostream>
#include <map>
template<typena me T1>
class A
{
public:
typedef T1 mem_type ;
T1 x ;
} ;
template<typena me T2>
void
foo( T2& var )
{
bar( var.x ) ; //This call compiles because of two-phase
construction.
//var.x is type-dependant, thus, its lookup is
delayed
//until template instantiation.
T2::mem_type val ; //This line is *not* affected by two-phase
lookup.
//Why not?
}
void
bar( int x )
{
std::cerr << x << std::endl ;
}
int
main( int argc, char* argv[] )
{
A<inta ;
a.x = 1 ;
foo( a ) ;
}
Does this mean that two-phase lookup applies only to function calls
and not variable instantiations? Judging from the second quote from
Stroustrup and this example, I'm guessing this is the case.
Thanks,
Paul

Interesting point. I do think that both are dependent names and will
require a two-phase lookup to resolve what function (bar -bar(int)) or
type (T2::mem_type -int) should be used.

I will need to check my copy of Stroustrup's book to see in what context
he mentions this to figure out what to make of it. I believe that he is
saying that if a dependent name is first encountered (first pass) the
compiler will assume it is a non-type.

This means:

T2::mem_type at the first pass will be assumed to be a variable or a
function (aka non-type). On the other hand, bar() on the first pass is
correctly parsed as a function, we just don't know which one.
I've added another example to show that this is how g++ 4.0.2 is in
fact working. Identifiers parsed are assumed to be a variable or
function until the second phase of lookup.
On the second pass, when all templates have been instantiated, it is
clear to the compiler that T2::mem_type is a type but the parse tree for
a type has already been generated and it flags it as an error (for GNU
and is probably "fixed on the fly" by Microsoft).
I read somewhere that Microsoft's VC6 is non-standards compliant in
this manner. Templates are not processed at all until the point of
instantiation. (Thus, no two-phase lookup.) VC7.1 also does this as an
extension that can be turned off. (/v or /i or /z can't recall atm)

bar() on the other
hand does some Koenig lookups and finds bar(int) satisfies the call.
Yes, according to stroustrup's book, bar() is resolved by normal
lookup at the point of instantiation, which includes koenig. Although,
koenig isn't invovled in this specific case.
BTW, you need to get into the habit of using typename in your examples
since, you bring up a valid question, does two-phase lookup occur on a
type but the compiler is complaining about a different thing: it is
confused as to whether or not the dependent name is a type or a
non-type. Which is why people reply to your post to simply add typename.
The point of the post was why adding typename worked. I found it
helpful to show the faulty code snippet rather than one that worked.
>
Hope that helps!
#include <iostream>
#include <map>

template<typena me T1>
class A
{
public:
typedef T1 mem_type ;
} ;

template<typena me T2>
void
foo( T2& var )
{
T2::mem_type( 3 ) ;
T2::mem_type = 4 ;
}

int
main( int argc, char* argv[] )
{
A<inta ;
a.x = 1 ;
foo( a ) ;
}

test.cc: In function 'void foo(T2&) [with T2 = A<int>]':
test.cc:32: instantiated from here
test.cc:17: error: dependent-name 'T2::mem_type' is parsed as a non-
type, but instantiation yields a type
test.cc:17: note: say 'typename T2::mem_type' if a type is meant
test.cc:18: error: dependent-name 'T2::mem_type' is parsed as a non-
type, but instantiation yields a type
test.cc:18: note: say 'typename T2::mem_type' if a type is meant

The point of this error-producing example is that both incorrect lines
are *not* flagged as errors until the second phase of lookup (template
instantiation). Therefore, the compiler (g++ at least) must be
assuming all encountered symbols are either function names or
variables and the typename identifies things as such and delays lookup
of the type until the second phase.

So, I now finally feel comfortable with that explanation. Although, I
would be interested to know what about the compiler implementation
prevents it from being able to determine the difference between
dependant and non-dependant typenames while being able to make this
determination for variables and functions.

Thanks,
Paul

Feb 8 '07 #8
On 8 Feb 2007 13:13:10 -0800, "pa************ ***@gmail.com"
<pa************ ***@gmail.comwr ote:

>BTW, you need to get into the habit of using typename in your examples
since, you bring up a valid question, does two-phase lookup occur on a
type but the compiler is complaining about a different thing: it is
confused as to whether or not the dependent name is a type or a
non-type. Which is why people reply to your post to simply add typename.

The point of the post was why adding typename worked. I found it
helpful to show the faulty code snippet rather than one that worked.
This has nothing to do with two-phase name resolution.

Although the compiler is not obliged to resolve names until the point of use,
it is still obliged to check the _syntax_ of your template definition, and it
has no way to do this unless it can tell which names refer to types, and which
names refer to variables.

14.6(2):

"A name used in a template declaration or definition and that is dependent on
a template-parameter is assumed not to name a type unless the applicable name
lookup finds a type name or the name is qualified by the keyword typename."
Example:

template <typename T>
void fn0()
{
typename T::a* p; // a is treated as a type defined in the scope of T,
// and p is a pointer to it.
}

template <typename T>
void fn1()
{
T::a* p; // a is treated as a static variable of T,
// multiplied by p.
}

-dr
Feb 9 '07 #9
On Feb 9, 1:05 am, Dave Rahardja <a...@me.comwro te:
On 8 Feb 2007 13:13:10 -0800, "paul.joseph.da ...@gmail.com"

<paul.joseph.da ...@gmail.comwr ote:
BTW, you need to get into the habit of using typename in your examples
since, you bring up a valid question, does two-phase lookup occur on a
type but the compiler is complaining about a different thing: it is
confused as to whether or not the dependent name is a type or a
non-type. Which is why people reply to your post to simply add typename.
The point of the post was why adding typename worked. I found it
helpful to show the faulty code snippet rather than one that worked.

This has nothing to do with two-phase name resolution.

Although the compiler is not obliged to resolve names until the point of use,
it is still obliged to check the _syntax_ of your template definition, and it
has no way to do this unless it can tell which names refer to types, and which
names refer to variables.
I don't have a copy of the standard, but as I read Stroustrup's book
the compiler *is* in fact obliged to resolve non-dependant names. And
further, what I've written is syntactically correct minus the
'typename' keyword. The question is 'Why is "typename" required?' I
understand its meaning is to tell the compiler that a given symbol is
a type vs. a variable. But the driving question is why is the compiler
able to tell in normal code yet not in template code?
14.6(2):

"A name used in a template declaration or definition and that is dependent on
a template-parameter is assumed not to name a type unless the applicable name
lookup finds a type name or the name is qualified by the keyword typename."
I haven't the slightest what this refers to. I'm assuming its the
standard. But this is *not* an answer to the underlying question of
why it is so. It is only a statment that it is so.
Example:

template <typename T>
void fn0()
{
typename T::a* p; // a is treated as a type defined in the scope of T,
// and p is a pointer to it.

}
Yep. If I tell the compiler something is a type, it believes me.
Again, why in this circumstance do I have to *tell* it specifically
that this is a type?

Why are we not writing code like:

typname int
main( typename int argc, typename char* argv[] )
{
typename int a = 4 ;
}
template <typename T>
void fn1()
{
T::a* p; // a is treated as a static variable of T,
// multiplied by p.

}

-dr
I believe this comment to be incoorect. T::a is not treated as a
static variable of T. This is a syntax error (According to Stroustrup
and g++ 4.0.2).

As far as I can tell, two-phase lookup is a method to delay looking up
symbols that it cannot define until a time when definition is
possible. This works for function calls and variable names as I have
shown. The question is, why not for types?

Stroustrup's line is something along the lines that "We cannot expect
compilers to be psychic." I haven't the slightest what this means,
because I've given an example that compiles a template referencing an
undefined symbol.

There has got to either be a theoretical or implementation reason for
this behavior. By theoretical, I mean there's an example that shows an
ambiguity when the compiler delays lookup of a type and implemenation
is more of a "this opens a can of worms best left closed" type of
answer (which is perfectly acceptable if it is indeed the answer).

That being said, I haven't been able to determine the reason for this
behavior. Only that this *is* the behavior.

Thanks,
Paul Davis

Feb 9 '07 #10

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

0
1786
by: SimonC | last post by:
I'm looking to do something similar to a feature found on Ticketmaster.com, where you select your seats at a venue, and then you have two minutes in which to take or leave them. QUESTION 1a. Inside (or just after) the same query that searches for available seats, I need to SIMULTANEOUSLY mark those seats as "on hold". I've only read about, but not yet used MySQL transactions, and wonder if this simultaneous "search-and-hold"...
8
1748
by: John Grenier | last post by:
Hi, I have to determine the "standing" (WIN - TIE - LOSS) from confrontations between two teams on a contest. The table matchResults has fields cont_id, team_id and contest_result (int). TABLE matchResults cont_id team_id contest_result 1 1 3 1 2 5
6
1883
by: Willem | last post by:
Hi, I have a newbie question: is it possible to make a search form in asp that searches in two different databases (access)? Willem
10
9384
by: Hank1234 | last post by:
Can I use one Data Adapter and one Command Builder to update amny tables? Currently in my data adapter I query two tables and fill them into two tables in a data set. When I make a change to a record in the second table and call the update method of the data adapter the command builders update command text is for the first table. Can the command builder handle two tables? Code example: Dim oCOnn As New SqlConnection("Data Source=.;" &...
6
4081
by: Matt K. | last post by:
Hi there, I have a form in an Access project that contains a subform which displays the results of a query of the style "select * from where = #a certain date#". In the main part of the form the user can change the date, which will force a requery in the subform to bring up records from the date selected. My question is this... The query in the subform is a very simple one, with only three fields being returned. In the interest of...
7
12894
by: Prabhudhas Peter | last post by:
I have two object instances of a same class... and i assigned values in both object instances (or the values can be taken from databse and assigned to the members of the objects)... Now i want to compare these two objects so that it will return true if both object's members have the same value... it is good if u can give me a single function or simple code snippet.. Thank U -- Peter...
0
1698
by: clintonG | last post by:
I applied aspnet_regsql to SQL2K which was working fine throughout Beta 2 development. After installing Visual Studio and SQL Express RTM my application has blown up. Logging in to the application became realllllllllllly slow. Content in LoginView Role Groups was not displaying even after a user in a role had logged in. It was taking about 15 seconds or so for the login control to display when the login link was selected on the homepage....
9
5269
by: Steven | last post by:
Hello, I have a question about strcmp(). I have four words, who need to be compared if it were two strings. I tried adding the comparison values like '(strcmp(w1, w2) + strcmp(w3, w4))', where w1 and w2 make up the first string and, w3 and w4 make up the second string. I do not want to allocate memory, then put the words together to create a string only to facilitate strcmp() comparison. My question; Does anyone know how to get the...
272
14121
by: Peter Olcott | last post by:
http://groups.google.com/group/comp.lang.c++/msg/a9092f0f6c9bf13a I think that the operator() member function does not work correctly, does anyone else know how to make a template for making two dimensional arrays from std::vectors ??? I want to use normal Array Syntax.
0
9568
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
0
9389
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
1
9335
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
9256
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
0
8257
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
1
6801
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
4709
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
1
3320
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
3
2218
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.