C++Talk.NET Forum Index C++Talk.NET
C++ language newsgroups
 
Archives   FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Using this-> from "C++ Templates"
Goto page 1, 2  Next
 
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ Language (Moderated)
View previous topic :: View next topic  
Author Message
Albrecht Fritzsche
Guest





PostPosted: Wed Mar 09, 2005 11:02 am    Post subject: Using this-> from "C++ Templates" Reply with quote



In 5.2 in the abovementioned book there is the following example

"template <typename T> class Base {
public:
void exit();
};
template <typename T> class Derived : Base<T> {
public:
void foo() {
exit(); // <-- calls external exit() or error
}
};

In this example, for resolving the symbol exit inside foo(), exit()
defined in Base is /never/ considered."

Why is this the case? Why is the Base's exit() never considered?

If I understand it correctly (the book seems to not mentioning it
explicitly) than the parser parsing Derived for the first time tries
to look up exit() immediately, but fails since there is no Base
Hence the trick is delaying the lookup via, for example, using this->?
Than, at instantiation time of Derived<T>, Base<T> can be constructed
too and hence, exit() exists. Right?

Thanks for any clearifications
Ali





Is the
this-> workaround required only for "dependent base classes"?

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
msalters
Guest





PostPosted: Wed Mar 09, 2005 3:56 pm    Post subject: Re: Using this-> from "C++ Templates" Reply with quote




Albrecht Fritzsche wrote:
Quote:
In 5.2 in the abovementioned book there is the following example

"template <typename T> class Base {
public:
void exit();
};
template <typename T> class Derived : Base<T> {
public:
void foo() {
exit(); // <-- calls external exit() or error
}
};

In this example, for resolving the symbol exit inside foo(),
exit()
defined in Base is /never/ considered."

Why is this the case? Why is the Base's exit() never considered?

Two-phase name lookup.

Quote:
If I understand it correctly (the book seems to not mentioning it
explicitly) than the parser parsing Derived for the first time tries
to look up exit() immediately, but fails since there is no Base

Actually, there may be a base<T> (for other reasons) but it simply
isn't considered. The first phase looks up names that are common to
all instantiations, i.e. don't depend on the precise nature of T.
Since the members of Base<T> can depend on the type T, they're not
included in this first lookup.

Quote:
Hence the trick is delaying the lookup via, for example, using
this->?
Than, at instantiation time of Derived<T>, Base<T> can be constructed
too and hence, exit() exists. Right?

Yes. this has type T*, so clearly any lookup which depends on the
type of 'this' can be done only when T* is known.

HTH,
Michiel Salters


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Thomas Maeder
Guest





PostPosted: Wed Mar 09, 2005 4:01 pm    Post subject: Re: Using this-> from "C++ Templates" Reply with quote



Albrecht Fritzsche <albrecht.fritzsche (AT) gmx (DOT) net> writes:

Quote:
"template <typename T> class Base {
public:
void exit();
};
template <typename T> class Derived : Base<T> {
public:
void foo() {
exit(); // <-- calls external exit() or error
}
};

In this example, for resolving the symbol exit inside foo(), exit()
defined in Base is /never/ considered."

Why is this the case? Why is the Base's exit() never considered?

What if I provide

template <>
class Base<MyType>
{
public:
void exit();
};

between the above code an the point of instantiation?


Quote:
If I understand it correctly (the book seems to not mentioning it
explicitly) than the parser parsing Derived for the first time tries
to look up exit() immediately, but fails since there is no Base<T>?

Members of base class templates are not considered, yes.


Quote:
Hence the trick is delaying the lookup via, for example, using this->?
Than, at instantiation time of Derived<T>, Base<T> can be constructed
too and hence, exit() exists. Right?

Prefixing exit() with this-> makes exit a dependant name,
yes. Dependant names are looked up at at instantiation time, while
nondependant names are looked up when the template itself is parsed.


The idea is that the compiler is able to report as many potential
problems as possible when it parses the template, to make its output
simpler and better understandable.

The parts of a template that do not depend on the template parameters
are thus treated first (and once only), and the dependant parts are
treated once per instantiation.

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]


Back to top
Falk Tannhäuser
Guest





PostPosted: Wed Mar 09, 2005 11:18 pm    Post subject: Re: Using this-> from "C++ Templates" Reply with quote

Albrecht Fritzsche wrote:
Quote:
In 5.2 in the abovementioned book there is the following example

"template <typename T> class Base {
public:
void exit();
};
template <typename T> class Derived : Base<T> {
public:
void foo() {
exit(); // <-- calls external exit() or error
}
};

In this example, for resolving the symbol exit inside foo(), exit()
defined in Base is /never/ considered."

Why is this the case? Why is the Base's exit() never considered?

The problem is that due to the possibility of partial specialisation,
the compiler can't know whether or not Base member function called 'exit()' before the actual instantiation of
the template (i.e. when T is known). Consider

template<> class Base<double> { /* no member function 'exit()' */ };

Derived<double> dd;
dd.foo(); // calls external exit() if any, or compilation error otherwise

Derived<int> di;
di.foo(); // Would call Base<int>::exit() in pre-standard C++ implementations
// According to Standard C++, lookup rules are the same as above

This silent change of semantics according to pre-standard name lookup
rules was considered to be a Bad Thing by the Fathers (and Mothers?)
of the Standard (and I don't think they were wrong ...), so the 2-phase
name lookup was introduced to avoid it. Having to write "this->exit()"
simply makes things clear both for the compiler and for the poor
maintenance programmer trying to understand what happens in these
cool template code he inherited...

For similar reasons (i.e. the existence of partial specialisation giving
the possibility to change the semantics of a template-parameter-dependent
symbol for example from typedef to member function / variable), the use
of "typename" keyword became mandatory in places where it was not required
in pre-standard C++ implementations.

Falk

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
David Abrahams
Guest





PostPosted: Wed Mar 09, 2005 11:31 pm    Post subject: Re: Using this-> from "C++ Templates" Reply with quote

Albrecht Fritzsche <albrecht.fritzsche (AT) gmx (DOT) net> writes:

Quote:
In 5.2 in the abovementioned book there is the following example

"template <typename T> class Base {
public:
void exit();
};
template <typename T> class Derived : Base<T> {
public:
void foo() {
exit(); // <-- calls external exit() or error
}
};

In this example, for resolving the symbol exit inside foo(), exit()
defined in Base is /never/ considered."

Why is this the case? Why is the Base's exit() never considered?

Them's the rules ;-)

But I hope this legal fragment will be more enlightening:

template class Base<T*> // specialize for pointers
{};

Or maybe this legal program will:

void exit();
template <class T> class Base;

template <class T> struct Derived
: Base<T>
{
void foo()
{
exit();
}
};

template <class T>
struct Base
{
void exit();
};

Quote:
If I understand it correctly (the book seems to not mentioning it
explicitly) than the parser parsing Derived for the first time tries
to look up exit() immediately, but fails since there is no Base<T>?

That's one way to look at it. Even if you've seen a primary template,
a specialization could come along later and change the meaning of
"exit," so really there is no Base<T> at that point.

Quote:
Hence the trick is delaying the lookup via, for example, using
this->?

Yep.

Quote:
Than, at instantiation time of Derived<T>, Base<T> can be constructed
too and hence, exit() exists. Right?

"Constructed" is not quite the right term. "Instantiated" would be
accurate.

Quote:
Is the this-> workaround required only for "dependent base classes"?

Yep. But some of us like to use it regardless, especially those of us who
like Python ;-)

--
Dave Abrahams
Boost Consulting
www.boost-consulting.com

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Stefan Strasser
Guest





PostPosted: Wed Mar 09, 2005 11:32 pm    Post subject: Re: Using this-> from "C++ Templates" Reply with quote

Albrecht Fritzsche schrieb:
Quote:
Why is this the case? Why is the Base's exit() never considered?

If I understand it correctly (the book seems to not mentioning it
explicitly) than the parser parsing Derived for the first time tries
to look up exit() immediately, but fails since there is no Base<T>?

Hence the trick is delaying the lookup via, for example, using this->?
Than, at instantiation time of Derived<T>, Base<T> can be constructed
too and hence, exit() exists. Right?


Is the
this-> workaround required only for "dependent base classes"?


you're right with both.
but note that there are compilers around which choose the wrong
exit()(e.g. gcc 3.3)
I think it's a good idea to use this-> to access members anyway, even if
you don't have to. it makes the code more readable without using a
member prefix like "m_"

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Albrecht Fritzsche
Guest





PostPosted: Thu Mar 10, 2005 12:08 am    Post subject: Re: Using this-> from "C++ Templates" Reply with quote

msalters wrote:
Quote:
Albrecht Fritzsche wrote:
If I understand it correctly (the book seems to not mentioning it
explicitly) than the parser parsing Derived for the first time tries
to look up exit() immediately, but fails since there is no Base<T>?

Actually, there may be a base<T> (for other reasons) but it simply
isn't considered. The first phase looks up names that are common to
all instantiations, i.e. don't depend on the precise nature of T.
Since the members of Base<T> can depend on the type T, they're not
included in this first lookup.

I still cannot imagine any names that are common to all instantiations -
a subtle specialization can change/redefine all names, can't it?

Can you give me please just one example of such a "common to all
instantions" name?

Cheers,
Ali

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Albrecht Fritzsche
Guest





PostPosted: Thu Mar 10, 2005 12:09 am    Post subject: Re: Using this-> from "C++ Templates" Reply with quote

Thomas Maeder wrote:

Quote:
The parts of a template that do not depend on the template parameters
are thus treated first (and once only)

What parts might that (theoretically) be? Are not all parts of a
template dependent, since their names can be reused/redefined in some
specializations?

Ali

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Thomas Maeder
Guest





PostPosted: Thu Mar 10, 2005 8:46 pm    Post subject: Re: Using this-> from "C++ Templates" Reply with quote

Albrecht Fritzsche <albrecht.fritzsche (AT) gmx (DOT) net> writes:

Quote:
Thomas Maeder wrote:

The parts of a template that do not depend on the template parameters
are thus treated first (and once only)

What parts might that (theoretically) be? Are not all parts of a
template dependent, since their names can be reused/redefined in some
specializations?

First and foremost the syntax. This is why we have to write typename
if a dependant name names a type.

Then, as I mentioned, accesses of entities through non-dependant names.

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
vandevoorde@gmail.com
Guest





PostPosted: Fri Mar 11, 2005 11:34 am    Post subject: Re: Using this-> from "C++ Templates" Reply with quote


Albrecht Fritzsche wrote:
Quote:
In 5.2 in the abovementioned book there is the following example

"template <typename T> class Base {
public:
void exit();
};
template <typename T> class Derived : Base<T> {
public:
void foo() {
exit(); // <-- calls external exit() or error
}
};

In this example, for resolving the symbol exit inside foo(),
exit()
defined in Base is /never/ considered."

Why is this the case? Why is the Base's exit() never considered?

If I understand it correctly (the book seems to not mentioning it
explicitly)

Did you have a chance to read section 9.4 (and especially 9.4.2)?
I think it says things pretty explicitly. Among other things, it says
on p. 137:

"nondependendent names are _not_ lookuped up in
dependent base classes (but they are still looked up
as soon as they are encountered)"

The section also explains why the language is that way (pretty
much what others have said in this thread).

Daveed


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]


Back to top
kanze@gabi-soft.fr
Guest





PostPosted: Sat Mar 12, 2005 1:51 am    Post subject: Re: Using this-> from "C++ Templates" Reply with quote

Albrecht Fritzsche wrote:
Quote:
Thomas Maeder wrote:

The parts of a template that do not depend on the template
parameters are thus treated first (and once only)

What parts might that (theoretically) be? Are not all parts of
a template dependent, since their names can be
reused/redefined in some specializations?

According to the standard, most names are not considered
dependent. This is a change with regards to what was current
practice before (and for not a little time after) the standard,
where fundamentally, all names where considered dependant (but
dependant name lookup used the same rules as normal name lookup,
applied at the point of instantiation).

The rules as to whether a name is dependant or not are extremely
complex; I'll admit that I have a great deal of trouble
understanding them. In the end, it's sort of a guessing game
you play with the compiler -- a game made even more interesting
by the fact that many compilers today don't implement all of the
rules correctly.

--
James Kanze GABI Software
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
kanze@gabi-soft.fr
Guest





PostPosted: Sat Mar 12, 2005 1:52 am    Post subject: Re: Using this-> from "C++ Templates" Reply with quote

Albrecht Fritzsche wrote:
Quote:
msalters wrote:
Albrecht Fritzsche wrote:
If I understand it correctly (the book seems to not
mentioning it explicitly) than the parser parsing Derived
for the first time tries to look up exit() immediately, but
fails since there is no Base<T>?

Actually, there may be a base<T> (for other reasons) but it
simply isn't considered. The first phase looks up names that
are common to all instantiations, i.e. don't depend on the
precise nature of T. Since the members of Base<T> can depend
on the type T, they're not included in this first lookup.

I still cannot imagine any names that are common to all
instantiations - a subtle specialization can change/redefine
all names, can't it?

Do you want it to be able to?

If you write a template which calls some global function, do you
want it to call a function in the base class simply because the
user has carelessly provided a function with the same name?

My personal opinion is that the problem of name hijacking isn't
all that great, and that even without two-phase look-up, there
were techniques to avoid it. Given the complexity of two-phase
look-up, I feel that the cure is worse than the disease; I
prefer the simpler rules that most compilers implemented in the
past. But it's a judgement call.

Quote:
Can you give me please just one example of such a "common to
all instantions" name?

The function called in case of assertion failure, in the macro
assert. Probably std::cerr, in some tracing statements (but the
std:: should suffice for that).

In practice, there are probably very few, if any, names which
would actually end up being redefined -- you don't know the name
of the function called in assert, but you know that it is a name
you can't legally use, so there should be no risk. Now that all
of the standard library is in std::, there should be no risk
there, either, and if I provide global functions that I want the
template to use, I can always put them in my own namespace, or
specify ::function() to avoid any risk as well. As I said,
we've introduced a lot of extra complexity to solve a problem
that doesn't actually occur much, if ever in practice.

--
James Kanze GABI Software
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Albrecht Fritzsche
Guest





PostPosted: Sat Mar 12, 2005 2:02 am    Post subject: Re: Using this-> from "C++ Templates" Reply with quote

[email]vandevoorde (AT) gmail (DOT) com[/email] wrote:
Quote:

Did you have a chance to read section 9.4 (and especially 9.4.2)?
I think it says things pretty explicitly.

Yes, I've read the mentioned pages and probably missed the important
pieces - lost in translation, so to speak.

Quote:
The section also explains why the language is that way

Hm, I still not see the advantage of it. Why does the language make
it so awkward to inherit from a dependent base class, ie that every
name from it has to be "qualified" with a leading this->? All I have
found was (on p 136) referring to early error diagnostics.

Is the other solution - ie making all names dependent(*) - so much
worse? It would, at least for the given examples, IMHO make the code
cleaner.

Cheers,
Ali

(*) possibly making names non-dependent via explicit scopes to
non-dependent names like ::exit() or Non_dependent_base::foo()

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]


Back to top
Ian Knowles
Guest





PostPosted: Sat Mar 12, 2005 2:11 am    Post subject: Re: Using this-> from "C++ Templates" Reply with quote

Stefan Strasser wrote:
Quote:
but note that there are compilers around which choose the wrong
exit()(e.g. gcc 3.3)

I've also tried using BCB6 and VC71 with the same results (a linker
error for undefined Base< T >::exit) although Comeau online identified
an error (too few arguments to the global "exit" function) in strict
mode.

I wonder if it is safe to assume that when newer compilers get this
right that compiler errors would occur rather than just different
runtime behaviour (as I have a lot of template code some of which may
well be strictly incorrect). :(

Regards,

Ian Knowles.


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
vandevoorde@gmail.com
Guest





PostPosted: Mon Mar 14, 2005 11:59 pm    Post subject: Re: Using this-> from "C++ Templates" Reply with quote


Albrecht Fritzsche wrote:
[...]
Quote:
Is the other solution - ie making all names dependent(*) - so much
worse? It would, at least for the given examples, IMHO make the code
cleaner.
[...]
(*) possibly making names non-dependent via explicit scopes to
non-dependent names like ::exit() or Non_dependent_base::foo()

I think it _would_ make things quite a bit wose, yes. E.g.,
you'd have to use many more "typename"s and "template"s.

E.g., today you might safely write in a member of a class with
a dependent base:

std::vector<int> lines_seen;

but that would then have to become:

typename std::template vector<int> lines_seen;

The reason older compilers got away with not requiring the keywords
is that they didn't parse templates in their generic form (i.e., they
used
macro-like techniques for template instantiations). However, mandating
such techniques makes all kinds of useful code analysis tools
(available
today) impossible to implement because a template does not have an
unambiguous grammatical structure until instantiated (i.e., a tool
cannot
reason about a template by itself).

Daveed


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]


Back to top
Display posts from previous:   
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ Language (Moderated) All times are GMT
Goto page 1, 2  Next
Page 1 of 2

 
Jump to:  
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


Powered by phpBB © 2001, 2006 phpBB Group
SEO toolkit © 2004-2006 webmedic.