qualified function names and two phase lookup

14 views
Skip to first unread message

Balog Pal

unread,
May 20, 2003, 12:08:42 PM5/20/03
to
Herb just runs GOTW on two phase lookup rules.

template<typename T>
class X : public Y<T> { // 1 ?
E f( int ) { // 2 ?
g(); // 3 ?
this->h(); // 4 ?

T t1, t2;
cout << t1; // 5 ?
swap( t1, t2 ); // 6 ?
std::swap( t1, t2 ); // 7 ?
}
};

The answers I've seen so far show lines 6 and 7 are different.

> See 14.6.2p1:
>
> "In an expression of the form:
>
> postfix-expression ( expression-list opt )
>
> where the postfix-expression is an identifier, the identifier denotes a
> dependent name if and only if any of the expressions in the
> expression-list is
> a type-dependent expression (14.6.2.2)."
>
> The key is that a qualified name is not an identifier, so this doesn't
> apply.

My question here is whether that was intended bahavior, or an overlook.
In the first case what is the rationale? I find this difference just
horrifying.

Intuitively I'd think qualification would remove ADL, and narrow the search
scope but _leave the lookup to the second phase_. Where the vital
information is present.

I put general purpose templates (stuff like swap) in a common file, that is
included early in every file.
Actual types are defined much later, functions using them even later. How
am I supposed to use namespaces to deal with this thing?

If that was not intended, is there a DR or some resolution expected anytime
soon?


Also, I'd look for the relevant part for std::swap as follows:
14.6.2p1 does not apply. (not matching the form)
14.6.2.2p1 does apply so it will be dependent unless exception found
14.6.2.2p2 does apply. the 'only if' secton at tail does not match. The
front bullets do not define exceptiontions.

So here I'd rule the expressions dependent. Then apply 14.6.4. Why's that
bad reasoning?


Paul


---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std...@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]

Gabriel Dos Reis

unread,
May 20, 2003, 3:29:34 PM5/20/03
to
pa...@lib.hu ("Balog Pal") writes:

| Herb just runs GOTW on two phase lookup rules.
|
| template<typename T>
| class X : public Y<T> { // 1 ?
| E f( int ) { // 2 ?
| g(); // 3 ?
| this->h(); // 4 ?
|
| T t1, t2;
| cout << t1; // 5 ?
| swap( t1, t2 ); // 6 ?
| std::swap( t1, t2 ); // 7 ?
| }
| };
|
| The answers I've seen so far show lines 6 and 7 are different.
|
| > See 14.6.2p1:
| >
| > "In an expression of the form:
| >
| > postfix-expression ( expression-list opt )
| >
| > where the postfix-expression is an identifier, the identifier denotes a
| > dependent name if and only if any of the expressions in the
| > expression-list is
| > a type-dependent expression (14.6.2.2)."
| >
| > The key is that a qualified name is not an identifier, so this doesn't
| > apply.
|
| My question here is whether that was intended bahavior, or an overlook.

>From various discussions I've seen on committee reflectors, that
always appeared to me as an intended behaviour.

| In the first case what is the rationale? I find this difference just
| horrifying.

What is horrifying about it? Please be specific.

| Intuitively I'd think qualification would remove ADL, and narrow the search
| scope but _leave the lookup to the second phase_. Where the vital
| information is present.

Which vital information? Clearly std::swap is an id-expression that
is NOT type-dependent, so from general rules, it makes sense it be
bound at the point of definition.

| I put general purpose templates (stuff like swap) in a common file, that is
| included early in every file.
| Actual types are defined much later, functions using them even later. How
| am I supposed to use namespaces to deal with this thing?

sounds like you want ADL :-)

| If that was not intended, is there a DR or some resolution expected anytime
| soon?
|
|
| Also, I'd look for the relevant part for std::swap as follows:
| 14.6.2p1 does not apply. (not matching the form)

right.

| 14.6.2.2p1 does apply so it will be dependent unless exception found
| 14.6.2.2p2 does apply. the 'only if' secton at tail does not match. The

how?

| front bullets do not define exceptiontions.
|
| So here I'd rule the expressions dependent. Then apply 14.6.4. Why's that
| bad reasoning?

Because you missed 14.6.2.2/3

An id-expression is type-dependent if it contains:
-- an identifier that was declared with a dependent type,
-- a template-id that is dependent,
-- a conversion-function-id that specifies a dependent type,
-- a nested-name-specifier that contains a class-name that names a
dependent type.

--
Gabriel Dos Reis, g...@integrable-solutions.net

Balog Pal

unread,
May 20, 2003, 8:08:11 PM5/20/03
to
"Gabriel Dos Reis" <g...@integrable-solutions.net> wrote in message
news:m3y911i...@uniton.integrable-solutions.net...

> What is horrifying about it? Please be specific.

Well. When I write foo(T) I want it to find some foo relevant to T at the
use point.
If I want to be more specific I say N::foo(T), and that will limit _where_
foo is searched, but nothing else.

Coming to templates the case is similar. I put foo(T), and expect the same.
Ant it will be the same. But if I want to be more specific wrt foo annd use
N::, it will change not only the searching scope, but also the WHEN the
lookup takes place, and moves the POINT to where I don't expect it.
Especially as T is nonexistent at that point.

> | Intuitively I'd think qualification would remove ADL, and narrow the
search
> | scope but _leave the lookup to the second phase_. Where the vital
> | information is present.
>
> Which vital information? Clearly std::swap is an id-expression that
> is NOT type-dependent

Using that logic swap is not tependent either. What the qualification
changes? The arguments make the expression dependent.

>, so from general rules, it makes sense it be
> bound at the point of definition.

I fail to see what is that sense right now. In case of swap I have
specialisations. Those will be defined _after_ this template. And I
expect those used.

And forget std::swap, think N::foo. I have a bunch of overloaded functions
in namespace N. (Possibly also a template.) I want the correct candidate
picked for foo. How that can be found at definition of the general template?

> sounds like you want ADL :-)

No, I want the regular lookup, just at the point of instantiation, not at
definition.

> | 14.6.2.2p1 does apply so it will be dependent unless exception found
> | 14.6.2.2p2 does apply. the 'only if' secton at tail does not match. The
>
> how?

DOH, I mistyped the second, it supposed to be p3 not p2.

> Because you missed 14.6.2.2/3
>
> An id-expression is type-dependent if it contains:
> -- an identifier that was declared with a dependent type,
> -- a template-id that is dependent,
> -- a conversion-function-id that specifies a dependent type,
> -- a nested-name-specifier that contains a class-name that names a
> dependent type.

This part says 'if', not 'if and only if'. So that does not add to
_exceptional_ cases. Just lists some explicit cases of dependent
id-expressions in my intrpretation.

Possibly that's the wrong interpretation.

Paul

Peter Dimov

unread,
May 21, 2003, 1:19:59 PM5/21/03
to
pa...@lib.hu ("Balog Pal") wrote in message news:<3eca...@andromeda.datanet.hu>...

> "Gabriel Dos Reis" <g...@integrable-solutions.net> wrote in message
> news:m3y911i...@uniton.integrable-solutions.net...
>
> > What is horrifying about it? Please be specific.
>
> Well. When I write foo(T) I want it to find some foo relevant to T at the
> use point.
> If I want to be more specific I say N::foo(T), and that will limit _where_
> foo is searched, but nothing else.
>
> Coming to templates the case is similar. I put foo(T), and expect the same.
> Ant it will be the same. But if I want to be more specific wrt foo annd use
> N::, it will change not only the searching scope, but also the WHEN the
> lookup takes place, and moves the POINT to where I don't expect it.
> Especially as T is nonexistent at that point.

It only looks counter-intuitive at first sight. ;-)

When you write foo(x) you enable both normal and argument dependent
lookup. When you qualify the function name - N::foo(x) - you
explicitly specify the namespace, and as a consequence, you inhibit
argument dependent lookup. Looks logical so far, right? Note that by
disabling ADL, you also disabled ADL in N::, but it doesn't matter at
this point.

Moving to templates. Point of definition does both normal and argument
dependent lookup, point of instantiation does ADL only (14.6.4/1.)

When you disable ADL by writing N::foo(x), the only lookup that
remains is normal lookup done at point of definition. Point of
instantiation lookup is implicitly disabled as a consequence of the
interaction between 3.4.2/1 and 14.6.4/1.

James Kanze

unread,
May 21, 2003, 1:21:45 PM5/21/03
to
g...@integrable-solutions.net (Gabriel Dos Reis) wrote in message
news:<m3y911i...@uniton.integrable-solutions.net>...

> | > See 14.6.2p1:

I suspect that it is half and half. I wouldn't be surprised if no one
actually considered the exact case, but it seems to follow from the
general rules.

> | In the first case what is the rationale? I find this difference just
> | horrifying.

> What is horrifying about it? Please be specific.

I'm not sure myself. (Horrifying is perhaps a bit strong, I find two
phase look-up a bit daunting to begin with.)

Just to be sure I understand what is going on, if I write:

void f( int ) { std::cout << "int\n" ; }
void f( long ) { std::cout << "long\n" ; }

template< typename T >
class C {
public:
C::C() { ::f( T() ) ; }
} ;

void f( char ) { std::cout << "char\n" ; }

int
main()
{
C<char> aC ;
return 0 ;
}

The output should be "int", and not "char". In other words, the
overload set is fixed at template definition, although the overload
resolution cannot actually take place until instantiation.

--
James Kanze GABI Software mailto:ka...@gabi-soft.fr
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
11 rue de Rambouillet, 78460 Chevreuse, France, Tél. : +33 (0)1 30 23 45 16

Daveed Vandevoorde

unread,
May 21, 2003, 3:27:24 PM5/21/03
to
pa...@lib.hu ("Balog Pal") wrote:
> Herb just runs GOTW on two phase lookup rules.
>
> template<typename T>
> class X : public Y<T> { // 1 ?
> E f( int ) { // 2 ?
> g(); // 3 ?
> this->h(); // 4 ?
>
> T t1, t2;
> cout << t1; // 5 ?
> swap( t1, t2 ); // 6 ?
> std::swap( t1, t2 ); // 7 ?
> }
> };
>
> The answers I've seen so far show lines 6 and 7 are different.

Indeed.

> > See 14.6.2p1:
> >
> > "In an expression of the form:
> >
> > postfix-expression ( expression-list opt )
> >
> > where the postfix-expression is an identifier, the identifier denotes a
> > dependent name if and only if any of the expressions in the
> > expression-list is
> > a type-dependent expression (14.6.2.2)."
> >
> > The key is that a qualified name is not an identifier, so this doesn't
> > apply.
>
> My question here is whether that was intended bahavior, or an overlook.

It was intended.

> In the first case what is the rationale? I find this difference just
> horrifying.
>
> Intuitively I'd think qualification would remove ADL, and narrow the search
> scope but _leave the lookup to the second phase_. Where the vital
> information is present.

Your intuition is correct, but you might be misunderstanding
the unqualified case. In line 6, swap undergoes both OL
(ordinary lookup) and ADL (argument-dependent lookup). The OL
part happens at the point of definition (phase 1), and the ADL
part happens at the POI (point of instantiation; phase 2). If
you remove the ADL part, you're left with a phase 1 lookup only.

So it makes sense that std::swap in line 7 is only looked up
using qualified name lookup in phase 1.

> I put general purpose templates (stuff like swap) in a common file, that is
> included early in every file.
> Actual types are defined much later, functions using them even later. How
> am I supposed to use namespaces to deal with this thing?

Well, if your std::swap is in scope already, there is no
problem. You'll still pick up specializations that appear
later on (because those are not selected by lookup), but
without ADL you won't pick up later std::swap overloads.

> If that was not intended, is there a DR or some resolution expected anytime
> soon?

It was entirely intended.

> Also, I'd look for the relevant part for std::swap as follows:
> 14.6.2p1 does not apply. (not matching the form)
> 14.6.2.2p1 does apply so it will be dependent unless exception found
> 14.6.2.2p2 does apply. the 'only if' secton at tail does not match. The
> front bullets do not define exceptiontions.
>
> So here I'd rule the expressions dependent. Then apply 14.6.4. Why's that
> bad reasoning?

I suspect you're confusing "dependent expression" and
"dependent name." The "name" std::swap is not dependent,
and therefore 14.6.4 does not apply. The expression
"std::swap(t1, t2)" is type-dependent, and hence it could
potentially cause another identifier to be a dependent
name (not an issue here, since it is a complete expression).

Daveed

Gabriel Dos Reis

unread,
May 21, 2003, 3:27:46 PM5/21/03
to
pa...@lib.hu ("Balog Pal") writes:

| "Gabriel Dos Reis" <g...@integrable-solutions.net> wrote in message
| news:m3y911i...@uniton.integrable-solutions.net...
|
| > What is horrifying about it? Please be specific.
|
| Well. When I write foo(T) I want it to find some foo relevant to T at the
| use point.

Not actually. foo(T) means take a foo among those that happen to be visible
at the point of definition of enclosing scope, and possibly those
reachable by looking at the T.

Think about

namespace M
{
void foo(double); // #1
}

namespace N
{
using namespace M;
void g(int i)
{
foo(i); // #2
}
}

namespace M
{
void foo(int); // #3
}

int main()
{
N::g(2);
}

Line #2 calls #1 not #3 even though when N::g is called a better foo
is #3.


| If I want to be more specific I say N::foo(T), and that will limit _where_
| foo is searched, but nothing else.

No. What you wrote is, please take that foo apparently in N, now.

| Coming to templates the case is similar.

Templates are *meta* linguistic constructs with respect to non-template
constructs. Arguments based on analogy are very suspicious.

| I put foo(T), and expect the same.
| Ant it will be the same. But if I want to be more specific wrt foo annd use
| N::, it will change not only the searching scope, but also the WHEN the
| lookup takes place, and moves the POINT to where I don't expect it.

There is nothing new. That already happens in the non-template case.

| Especially as T is nonexistent at that point.

That is immaterial: T is a meta-variable. T does not need to be
present before defining meta-abstractions operating on it.

| > | Intuitively I'd think qualification would remove ADL, and narrow the
| search
| > | scope but _leave the lookup to the second phase_. Where the vital
| > | information is present.
| >
| > Which vital information? Clearly std::swap is an id-expression that
| > is NOT type-dependent
|
| Using that logic swap is not tependent either.

See the appropriate definition of being dependent.

| What the qualification changes?

scoping.

| The arguments make the expression dependent.

Yes but not the qualified-id.

It seems you're using templates where actually what you want is macro
expansion.

| >, so from general rules, it makes sense it be
| > bound at the point of definition.
|
| I fail to see what is that sense right now. In case of swap I have
| specialisations.

If you have *specializations* then you don't need to worry anout
anything. Because name lookup does not find specializations. It
finds primary templates, and specializations are selected by matching
partial specializations

| Those will be defined _after_ this template. And I
| expect those used.

It is a specialization, then it will be found.

| And forget std::swap, think N::foo.

That is immaterial for this particular discussion. But I'll
concentrate on your foo.

| I have a bunch of overloaded functions in namespace N.

Please do make a clear distinction bewteen overloads and
specializations. The two things do not follow the same name lookup rules.

| (Possibly also a template.) I want the correct candidate
| picked for foo. How that can be found at definition of the general template?

Write your template and/or your functions so that they can be found.
That is the general answer I can give to the general question. If you
have specific issue then write it out and I'll try to address it.

| > sounds like you want ADL :-)
|
| No, I want the regular lookup, just at the point of instantiation, not at
| definition.

so actually you want macro substitution. That is a possible template
design, but none that I would like to have. See the recent discussion
on export and whish list point of not intereferring with the meaning
of an instantiation.

the choice was deliberate: early binding when possible.

| > | 14.6.2.2p1 does apply so it will be dependent unless exception found
| > | 14.6.2.2p2 does apply. the 'only if' secton at tail does not match. The
| >
| > how?
|
| DOH, I mistyped the second, it supposed to be p3 not p2.
|
| > Because you missed 14.6.2.2/3
| >
| > An id-expression is type-dependent if it contains:
| > -- an identifier that was declared with a dependent type,
| > -- a template-id that is dependent,
| > -- a conversion-function-id that specifies a dependent type,
| > -- a nested-name-specifier that contains a class-name that names a
| > dependent type.
|
| This part says 'if', not 'if and only if'. So that does not add to
| _exceptional_ cases. Just lists some explicit cases of dependent
| id-expressions in my intrpretation.
|
| Possibly that's the wrong interpretation.

The above is a definition and it does not need to be phrased in terms
of "if and only if". All it says is what it means for an
id-expression to be *type*-dependent. Since none of the bullets here,
nor found in the general definition of "dependent name" says a
qualified-id, the nested-name-specified of which is not dependent,
is dependent you cannot conclude that such a thing is dependent.

--
Gabriel Dos Reis, g...@integrable-solutions.net

---

Terje Slettebø

unread,
May 21, 2003, 3:28:02 PM5/21/03
to
""Balog Pal"" <pa...@lib.hu> wrote in message
news:3eca...@andromeda.datanet.hu...

> "Gabriel Dos Reis" <g...@integrable-solutions.net> wrote in message
> news:m3y911i...@uniton.integrable-solutions.net...
>
> And forget std::swap, think N::foo. I have a bunch of overloaded functions
> in namespace N. (Possibly also a template.) I want the correct candidate
> picked for foo. How that can be found at definition of the general
template?
>
> > sounds like you want ADL :-)
>
> No, I want the regular lookup, just at the point of instantiation, not at
> definition.

It seems that you don't get one, using the current standard. For example the
following fails to compile on Comeau C++:

namespace test
{
}

template<class T>
void A()
{
test::f(T()); // error: namespace "test" has no member "f"
}

namespace test
{
template<class T>
void f(T) {}
}

int main()
{
A<int>();
}


Regards,

Terje

William M. Miller

unread,
May 21, 2003, 3:28:21 PM5/21/03
to
""Balog Pal"" <pa...@lib.hu> wrote in message
news:3eca...@andromeda.datanet.hu...
> "Gabriel Dos Reis" <g...@integrable-solutions.net> wrote in message
> news:m3y911i...@uniton.integrable-solutions.net...
>
> > What is horrifying about it? Please be specific.
>
> Well. When I write foo(T) I want it to find some foo relevant to T at the
> use point.
> If I want to be more specific I say N::foo(T), and that will limit _where_
> foo is searched, but nothing else.
>
> Coming to templates the case is similar. I put foo(T), and expect the
same.
> Ant it will be the same. But if I want to be more specific wrt foo annd
use
> N::, it will change not only the searching scope, but also the WHEN the
> lookup takes place, and moves the POINT to where I don't expect it.
> Especially as T is nonexistent at that point.

Expressions inside templates are different from expressions in
other contexts. Ordinary expressions only have a single point
of context. In a template, you have both the definition context
and the instantiation context. Somehow the contexts have to be
merged. The mechanism you want would involve ordinary (lexical)
lookup from both contexts. (I mean that some names would require
ordinary lookup from the definition context and others from the
instantiation context, not necessarily that the same name would
be looked up in both -- although some would like that feature, as
well.) The Committee decided that that was too difficult and
confusing, so it eliminated the lexical lookup from the
instantiation context. More below.

> > | Intuitively I'd think qualification would remove ADL, and narrow the
> search
> > | scope but _leave the lookup to the second phase_. Where the vital
> > | information is present.
> >
> > Which vital information? Clearly std::swap is an id-expression that
> > is NOT type-dependent
>
> Using that logic swap is not tependent either. What the qualification
> changes? The arguments make the expression dependent.

No, the arguments are only considered for unqualified names, not
for qualified names.

> >, so from general rules, it makes sense it be
> > bound at the point of definition.
>
> I fail to see what is that sense right now. In case of swap I have
> specialisations. Those will be defined _after_ this template. And I
> expect those used.

I think that's okay -- see 14.6.4.1p1. I believe that in the case
you're concerned about, the point of instantiation of swap will be
at the point of instantiation of the containing specialization,
which will be after your explicit specializations.

> And forget std::swap, think N::foo. I have a bunch of overloaded functions
> in namespace N. (Possibly also a template.) I want the correct candidate
> picked for foo. How that can be found at definition of the general
template?

They have to be visible from the definition. (As I mentioned, the
explicit specializations can come after the definition, but
ordinary overloads must be visible before the definition.) To me,
this makes sense. If you write "N::foo" inside your template, I
would expect that N and foo would be declared before the template
definition. Overload resolution, of course, is done using the
actual argument types in the specialization; it's just choosing
from the overloads visible at the point of the definition.

> > sounds like you want ADL :-)
>
> No, I want the regular lookup, just at the point of instantiation, not at
> definition.

As I mentioned above, the Committee decided that doing ordinary
lookup at the point of definition was too hard. This was part
of the Stockholm compromise that allowed the Committee to agree
on separate compilation of templates ("export").

Consider a template definition in translation unit A. Clearly
references to other things in A must be resolved by ordinary
lexical lookup, so the compiler must essentially compile the
specialization of the template in the context of A, just as if
it were an ordinary function.

Equally obviously, some references from the template
specialization can refer to things declared in translation
unit B, where its point of instantiation occurs. Merging the
entire context of the point of instantiation into the
definition context would be difficult and expensive (expecially
if you have nested instantiations, where a given specialization
might cause instantiation of another template, which might
itself cause another instantion, to an arbitrary depth of
recursion).

The compromise that was reached was to say that lexical lookup
would occur only in the definition context; only ADL would be
performed in the instantiation context. Since qualified
function names do not participate in ADL, any arguments in a
call to a qualified name are ignored in determining whether a
qualified name is dependent or not.

> > Because you missed 14.6.2.2/3
> >
> > An id-expression is type-dependent if it contains:
> > -- an identifier that was declared with a dependent type,
> > -- a template-id that is dependent,
> > -- a conversion-function-id that specifies a dependent type,
> > -- a nested-name-specifier that contains a class-name that names a
> > dependent type.
>
> This part says 'if', not 'if and only if'. So that does not add to
> _exceptional_ cases. Just lists some explicit cases of dependent
> id-expressions in my intrpretation.
>
> Possibly that's the wrong interpretation.

Yes; this list is intended to be exhaustive. An id-expression is
only dependent if it satisfies one of those criteria. The
function call expression of which such an id-expression is a part
will be dependent if any of its argument expressions are, but that
doesn't affect the lookup of the names in the id-expression. (The
arguments only affect the lookup of an unqualified function name
because of the explicit provision in 14.6.2p1.)

-- William M. Miller

William M. Miller

unread,
May 21, 2003, 3:28:24 PM5/21/03
to
"James Kanze" <ka...@gabi-soft.de> wrote in message
news:d6651fb6.03052...@posting.google.com...

>
> Just to be sure I understand what is going on, if I write:
>
> void f( int ) { std::cout << "int\n" ; }
> void f( long ) { std::cout << "long\n" ; }
>
> template< typename T >
> class C {
> public:
> C::C() { ::f( T() ) ; }
> } ;
>
> void f( char ) { std::cout << "char\n" ; }
>
> int
> main()
> {
> C<char> aC ;
> return 0 ;
> }
>
> The output should be "int", and not "char". In other words, the
> overload set is fixed at template definition, although the overload
> resolution cannot actually take place until instantiation.

That's correct. See the example in 14.6.3 -- even though it's
an unqualified name there and qualified in your example, in
both cases it's a non-dependent name lookup that's done, so the
outcome is the same.

-- William M. Miller

Terje Slettebø

unread,
May 22, 2003, 1:01:04 AM5/22/03
to
"Daveed Vandevoorde" <goo...@vandevoorde.com> wrote in message
news:52f2f9cd.03052...@posting.google.com...

> pa...@lib.hu ("Balog Pal") wrote:
>
> > I put general purpose templates (stuff like swap) in a common file,
that is
> > included early in every file.
> > Actual types are defined much later, functions using them even later.
How
> > am I supposed to use namespaces to deal with this thing?
>
> Well, if your std::swap is in scope already, there is no
> problem. You'll still pick up specializations that appear
> later on (because those are not selected by lookup), but
> without ADL you won't pick up later std::swap overloads.

Well, that's ok, as you're not allowed to overload names in the standard
library, anyway. ;)

That leaves specialisation, although without partial specialisation of
function templates, you can't make a swap for a template type, e.g.:

// Not legal C++

namespace std
{
template<class T>
void swap<my_type<T>, my_type<T> >(...) { ... }
}

Although there's a proposal for this...
(http://anubis.dkuug.dk/jtc1/sc22/wg21/docs/papers/2001/n1295.htm). This
link appears messed up, though, as it gives another document. Anyway, the
paper is, "Partial Specialization of Function Templates" by Peter Dimov. I
found it in Google's cache, however
(http://216.239.57.100/search?q=cache:ThsG0C8TKyAJ:std.dkuug.dk/jtc1/sc22/wg
21/docs/papers/2001/n1295.htm).


Regards,

Terje

Peter Dimov

unread,
May 22, 2003, 9:01:30 AM5/22/03
to
tsle...@chello.no.nospam ("Terje Slettebř") wrote in message news:<ZKSya.7957$KF1.134230@amstwist00>...

> "Daveed Vandevoorde" <goo...@vandevoorde.com> wrote in message
> news:52f2f9cd.03052...@posting.google.com...
> > pa...@lib.hu ("Balog Pal") wrote:
> >
> > > I put general purpose templates (stuff like swap) in a common file,
> that is
> > > included early in every file.
> > > Actual types are defined much later, functions using them even later.
> How
> > > am I supposed to use namespaces to deal with this thing?
> >
> > Well, if your std::swap is in scope already, there is no
> > problem. You'll still pick up specializations that appear
> > later on (because those are not selected by lookup), but
> > without ADL you won't pick up later std::swap overloads.
>
> Well, that's ok, as you're not allowed to overload names in the standard
> library, anyway. ;)

But the standard library is. For example, <vector> contains an
overload for std::swap. This means that

#include <vector>
#include <algorithm>

is different than

#include <algorithm>
#include <vector>

Nifty, huh?

Dag Henriksson

unread,
May 22, 2003, 9:01:39 AM5/22/03
to
"James Kanze" <ka...@gabi-soft.de> wrote in message
news:d6651fb6.03052...@posting.google.com...

> Just to be sure I understand what is going on, if I write:


>
> void f( int ) { std::cout << "int\n" ; }
> void f( long ) { std::cout << "long\n" ; }
>
> template< typename T >
> class C {
> public:
> C::C() { ::f( T() ) ; }
> } ;
>
> void f( char ) { std::cout << "char\n" ; }
>
> int
> main()
> {
> C<char> aC ;
> return 0 ;
> }
>
> The output should be "int", and not "char". In other words, the

Yes, and it should be that even if you write
C() { f( T() ) ; }

See 14.6.4p1

--
Dag Henriksson

Thomas Witt

unread,
May 22, 2003, 11:14:25 AM5/22/03
to

Hi,

Peter Dimov wrote:
> tsle...@chello.no.nospam ("Terje Slettebø") wrote in message news:<ZKSya.7957$KF1.134230@amstwist00>...


>>Well, that's ok, as you're not allowed to overload names in the standard
>>library, anyway. ;)
>
>
> But the standard library is. For example, <vector> contains an
> overload for std::swap. This means that
>
> #include <vector>
> #include <algorithm>
>
> is different than
>
> #include <algorithm>
> #include <vector>
>
> Nifty, huh?

This starts to get scary.

Thomas

--
Dipl.-Ing. Thomas Witt
Institut fuer Verkehrswesen, Eisenbahnbau und -betrieb, Universitaet
Hannover
voice: +49(0) 511 762 - 4273, fax: +49(0) 511 762-3001
http://www.ive.uni-hannover.de

Terje Slettebø

unread,
May 22, 2003, 1:42:17 PM5/22/03
to
"Peter Dimov" <pdi...@mmltd.net> wrote in message
news:7dc3b1ea.03052...@posting.google.com...

*wince*

I guess there was a reason for your proposal for partial specialisation of
function templates. :) The above makes all the more reason to use
specialisation rather than overloading for this, as it's not
order-dependent.


Regards,

Terje

Gabriel Dos Reis

unread,
May 22, 2003, 1:42:33 PM5/22/03
to
pdi...@mmltd.net (Peter Dimov) writes:

[...]

| #include <vector>
| #include <algorithm>
|
| is different than

^^

| #include <algorithm>
| #include <vector>

Not is. But *may*.

--
Gabriel Dos Reis, g...@integrable-solutions.net

---

LLeweLLyn

unread,
May 22, 2003, 2:02:14 PM5/22/03
to
pdi...@mmltd.net (Peter Dimov) writes:

> tsle...@chello.no.nospam ("Terje Slettebø") wrote in message


> news:<ZKSya.7957$KF1.134230@amstwist00>...
> > "Daveed Vandevoorde" <goo...@vandevoorde.com> wrote in message
> > news:52f2f9cd.03052...@posting.google.com...
> > > pa...@lib.hu ("Balog Pal") wrote:
> > >
> > > > I put general purpose templates (stuff like swap) in a common file,
> > that is
> > > > included early in every file.
> > > > Actual types are defined much later, functions using them even later.
> > How
> > > > am I supposed to use namespaces to deal with this thing?
> > >
> > > Well, if your std::swap is in scope already, there is no
> > > problem. You'll still pick up specializations that appear
> > > later on (because those are not selected by lookup), but
> > > without ADL you won't pick up later std::swap overloads.
> >
> > Well, that's ok, as you're not allowed to overload names in the standard
> > library, anyway. ;)
>
> But the standard library is. For example, <vector> contains an
> overload for std::swap. This means that
>
> #include <vector>
> #include <algorithm>
>
> is different than
>
> #include <algorithm>
> #include <vector>
>
> Nifty, huh?

I thought standard headers were supposed have a meaning independent of
their order of inclusion. I think 17.4.2.1/2 supports this:

A translation unit may include library headers in any order
(clause 2). Each may be included more than once, with no effect
different from being included exactly once, except that the effect
of including either <cassert> or <assert.h> depends each time on
the lexically current definition of NDEBUG. (161)

If your interpretation of the lookup of std::swap is correct, and my
interpretation of 17.4.2.1/2 is correct, I think a DR is in order.

Balog Pal

unread,
May 22, 2003, 2:38:53 PM5/22/03
to
Okey, thanks everyone, I learned a lot!

Paul

Gabriel Dos Reis

unread,
May 22, 2003, 2:40:36 PM5/22/03
to
ka...@gabi-soft.de (James Kanze) writes:

[...]

| > >From various discussions I've seen on committee reflectors, that
| > always appeared to me as an intended behaviour.
|
| I suspect that it is half and half.

Ask the people who wrote that part. I'm pretty sure they will tell
you it was a deliberate decision.

[...]

| Just to be sure I understand what is going on, if I write:
|
| void f( int ) { std::cout << "int\n" ; }
| void f( long ) { std::cout << "long\n" ; }
|
| template< typename T >
| class C {
| public:
| C::C() { ::f( T() ) ; }
| } ;
|
| void f( char ) { std::cout << "char\n" ; }
|
| int
| main()
| {
| C<char> aC ;
| return 0 ;
| }
|
| The output should be "int", and not "char".

Yes. That should output the same thing even if you didn't explicilty
qualify f. There are some compilers out there that get that wrong
(GCC-3.2.x is a notable example).

--
Gabriel Dos Reis, g...@integrable-solutions.net

---

Howard Hinnant

unread,
May 22, 2003, 2:47:34 PM5/22/03
to
In article <m14r3ma...@localhost.localdomain>, LLeweLLyn
<llewe...@xmission.dot.com> wrote:

| > But the standard library is. For example, <vector> contains an
| > overload for std::swap. This means that
| >
| > #include <vector>
| > #include <algorithm>
| >
| > is different than
| >
| > #include <algorithm>
| > #include <vector>
| >
| > Nifty, huh?
|
| I thought standard headers were supposed have a meaning independent of
| their order of inclusion. I think 17.4.2.1/2 supports this:
|
| A translation unit may include library headers in any order
| (clause 2). Each may be included more than once, with no effect
| different from being included exactly once, except that the effect
| of including either <cassert> or <assert.h> depends each time on
| the lexically current definition of NDEBUG. (161)
|
| If your interpretation of the lookup of std::swap is correct, and my
| interpretation of 17.4.2.1/2 is correct, I think a DR is in order.

This is fixed in:

http://anubis.dkuug.dk/jtc1/sc22/wg21/docs/papers/2003/n1439.htm

which hasn't been accepted yet, but the lwg has informally agreed with
the general approach.

--
Howard Hinnant
Metrowerks

Gabriel Dos Reis

unread,
May 25, 2003, 10:33:17 AM5/25/03
to
tsle...@chello.no.nospam ("Terje Slettebø") writes:

| I guess there was a reason for your proposal for partial specialisation of
| function templates. :) The above makes all the more reason to use
| specialisation rather than overloading for this, as it's not
| order-dependent.

But it can be translation unit dependent.

--
Gabriel Dos Reis, g...@integrable-solutions.net

---

Terje Slettebø

unread,
May 25, 2003, 8:45:47 PM5/25/03
to
"Gabriel Dos Reis" <g...@integrable-solutions.net> wrote in message
news:m3d6ia6...@uniton.integrable-solutions.net...

tsle...@chello.no.nospam ("Terje Slettebø") writes:

>| I guess there was a reason for your proposal for partial specialisation
of
>| function templates. :) The above makes all the more reason to use
>| specialisation rather than overloading for this, as it's not
>| order-dependent.

>But it can be translation unit dependent.

In what way? Of course, if the compiler hasn't seen the specialisation,
before it's bound at the point of instantiation, it can't use it.


Regards,

Terje

Gabriel Dos Reis

unread,
May 27, 2003, 1:13:18 PM5/27/03
to
tsle...@chello.no.nospam ("Terje Slettebø") writes:

| "Gabriel Dos Reis" <g...@integrable-solutions.net> wrote in message
| news:m3d6ia6...@uniton.integrable-solutions.net...
| tsle...@chello.no.nospam ("Terje Slettebø") writes:
|
| >| I guess there was a reason for your proposal for partial specialisation
| of
| >| function templates. :) The above makes all the more reason to use
| >| specialisation rather than overloading for this, as it's not
| >| order-dependent.
|
| >But it can be translation unit dependent.
|
| In what way? Of course, if the compiler hasn't seen the specialisation,
| before it's bound at the point of instantiation, it can't use it.

So, you answer your own question: The set of specializations ought
to be the same in every translation unit in a consistent manner,
or else bad things may silently happen.

--
Gabriel Dos Reis, g...@integrable-solutions.net

---

faisal vali

unread,
May 27, 2003, 1:19:00 PM5/27/03
to

"Terje Slettebø" wrote:
>
<snip>


>
> Although there's a proposal for this...
> (http://anubis.dkuug.dk/jtc1/sc22/wg21/docs/papers/2001/n1295.htm). This
> link appears messed up, though, as it gives another document. Anyway, the
> paper is, "Partial Specialization of Function Templates" by Peter Dimov.


Does anyone know why this link is messed up?

If no decision has been made by the committee yet, perhaps this proposal
needs to be resubmitted (like the local classes proposal had to be
resubmitted)?

regards,
Faisal Vali

James Kanze

unread,
Jun 15, 2003, 6:13:53 PM6/15/03
to
dag.hen...@quidsoft.se ("Dag Henriksson") writes:

|> "James Kanze" <ka...@gabi-soft.de> wrote in message
|> news:d6651fb6.03052...@posting.google.com...

|> > Just to be sure I understand what is going on, if I write:

|> > void f( int ) { std::cout << "int\n" ; }
|> > void f( long ) { std::cout << "long\n" ; }

|> > template< typename T >
|> > class C {
|> > public:
|> > C::C() { ::f( T() ) ; }
|> > } ;

|> > void f( char ) { std::cout << "char\n" ; }

|> > int
|> > main()
|> > {
|> > C<char> aC ;
|> > return 0 ;
|> > }

|> > The output should be "int", and not "char". In other words, the

|> Yes, and it should be that even if you write
|> C() { f( T() ) ; }

|> See 14.6.4p1

Now I'm really confused. If I don't use the qualifier, why doesn't
14.6.2 apply? I have an "expression of the form:

postfix-expression ( expression-list[opt] )

where the postfix-expression is an identifier", and T() is a type
dependant expression, and so I would expect that "the identifier
denotes a dependant name".

And if the name is dependant, shouldn't look up be deferred until the
point of instantiation?

--
James Kanze mailto:ka...@gabi-soft.fr


Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung

11 rue de Rambouillet, 78460 Chevreuse, France Tel. +33 1 41 89 80 93

James Kanze

unread,
Jun 16, 2003, 3:40:03 PM6/16/03
to
wi...@ive.uni-hannover.de (Thomas Witt) writes:

|> Peter Dimov wrote:
|> > tsle...@chello.no.nospam ("Terje Slettebø") wrote in message news:<ZKSya.7957$KF1.134230@amstwist00>...
|> >>Well, that's ok, as you're not allowed to overload names in the standard
|> >>library, anyway. ;)
|> > But the standard library is. For example, <vector> contains an
|> > overload for std::swap. This means that
|> > #include <vector>
|> > #include <algorithm>
|> > is different than
|> > #include <algorithm>
|> > #include <vector>
|> > Nifty, huh?

|> This starts to get scary.

Starts? I consider myself probably better than average, and I'm
totally incapable of understanding what happens in name lookup in
templates more than half the time. I rather suspect that we've ended
up with something so complicated that it cannot be safely used in real
projects.

--
James Kanze mailto:ka...@gabi-soft.fr
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
11 rue de Rambouillet, 78460 Chevreuse, France Tel. +33 1 41 89 80 93

---

William M. Miller

unread,
Jun 16, 2003, 9:39:26 PM6/16/03
to
"James Kanze" <ka...@alex.gabi-soft.fr> wrote in message
news:86ptlfc...@alex.gabi-soft.fr...

Yes, that's true. However, the lookup of a dependent name involves
only:

- Declarations that are visible at the point of definition of
the template

- Declarations from namespaces associated with the types of the
function arguments both from the instantiation context
(14.6.4.1) and from the definition context

(14.6.4p1). In this example, the types of the function arguments
are all fundamental types, which have no associated classes or
namespaces (3.4.2p2), so the only declarations available for
consideration are the ones visible at the point of definition. It
would be different if you had used a class type instead of char.

-- William M. Miller

Gabriel Dos Reis

unread,
Jun 20, 2003, 3:34:17 PM6/20/03
to
ka...@alex.gabi-soft.fr (James Kanze) writes:

Yes, "f" is considered to be a dependent name.

| And if the name is dependant, shouldn't look up be deferred until the
| point of instantiation?

Dependent name lookup resolution is explained in 14.6.4/1 which says:

In resolving dependent names, names from the following sources are
considered:
-- Declarations that are visible at the point of definition of the
template.
-- Declarations from namespaces associated with the types of the
function arguments both from the instan-tiation context (14.6.4.1)
and from the definition context.

In the above example, at the point of definition, ordinary name lookup
finds

void f(int);
void f(long);

Because, the set of associated namespaces of the template argument
"char" is empty, name lookup in the instantiation context sees
nothing. Hence Dag's comment.

--
Gabriel Dos Reis, g...@integrable-solutions.net

---

Terje Slettebø

unread,
Jun 20, 2003, 3:34:42 PM6/20/03
to
"James Kanze" <ka...@alex.gabi-soft.fr> wrote in message
news:86ptlfc...@alex.gabi-soft.fr...

As Daveed Vandevoorde said in another posting, dependent names are
looked up using both ordinary lookup (OL) and ADL. The OL happens in the
definition context, while the ADL happens in the instantiation context.
As int is used, there's no associated namespaces or classes, so the ADL
lookup doesn't return anything, and the binding at the OL is used.

It becomes even more clear if you remove f(int) and f(long), and it will
then give an error about undefined "f". Also, try using a UDT for
instantiation, instead, and an overloaded function for it, defined after
the class template but before main. It should then be selected.

I guess what is confusing, here, is that 14.6.2/1 says: "Such names are
unbound and are looked up at the point of the template instantiation
(14.6.4.1) in both the context of the template definition and the
context of the point of instantiation."

However, when we look at the paragraph about dependent name resolution
(14.6.4/1), it says:

"In resolving dependent names, names from the following sources are
considered:

- Declarations that are visible at the point of definition of the
template.

- Declarations from namespaces associated with the types of the function

arguments both from the instantiation context (14.6.4.1) and from the
definition context."

So it appears that the lookup in 14.6.2/1 refers to the OL in the
definition context, and ADL in the instantiation context.


Regards,

Terje

David Abrahams

unread,
Jun 20, 2003, 3:35:24 PM6/20/03
to
ka...@alex.gabi-soft.fr (James Kanze) writes:

> wi...@ive.uni-hannover.de (Thomas Witt) writes:
>
> |> Peter Dimov wrote:
> |> > tsle...@chello.no.nospam ("Terje Slettebø") wrote in message news:<ZKSya.7957$KF1.134230@amstwist00>...
> |> >>Well, that's ok, as you're not allowed to overload names in the standard
> |> >>library, anyway. ;)
> |> > But the standard library is. For example, <vector> contains an
> |> > overload for std::swap. This means that
> |> > #include <vector>
> |> > #include <algorithm>
> |> > is different than
> |> > #include <algorithm>
> |> > #include <vector>
> |> > Nifty, huh?
>
> |> This starts to get scary.
>
> Starts? I consider myself probably better than average, and I'm
> totally incapable of understanding what happens in name lookup in
> templates more than half the time. I rather suspect that we've ended
> up with something so complicated that it cannot be safely used in real
> projects.

P'raps so. I wrote a paper about some of these problems:
http://www.boost-consulting.com/writing/qn.html

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

faisal vali

unread,
Jun 23, 2003, 11:42:35 PM6/23/03
to

Terje Slettebø wrote:
>
<snip>

> As Daveed Vandevoorde said in another posting, dependent names are
> looked up using both ordinary lookup (OL) and ADL. The OL happens in the
> definition context, while the ADL happens in the instantiation context.
> As int is used, there's no associated namespaces or classes, so the ADL
> lookup doesn't return anything, and the binding at the OL is used.

It was my understanding that ADL also occurs at the point of definition
along with OL.

Consider the following example:

namespace B { struct S; }

namespace A
{
struct S { };
struct R { };
void f(S); // -- 0
void f(int, S, R); // -- 1
}

namespace B
{
using namespace A;

struct S { };
struct R { };
void f(char, S, R); // -- 2
template<class T1, class T2, class T3> void f(T1,T2,T3); // -- 3
}

struct S { };
struct R { };

void f(bool, S, R); // -- 4

template<class PT, class UDT>
void foo()
{
f(PT(), B::S(), UDT());

}

namespace A
{
void f(int, B::S ,int); // -- 5
}

void f(int, B::S, int); // -- 6

namespace B
{
void f(int, int, int); // -- 7
}

void f(int, B::S, R); // -- 8

The definition context adds the following candidates to the overload
set:

a) 4 -> OL
b) 2 -> ADL
c) 3 -> ADL


foo<char,B::R>();
-- POI lookup will perform ONLY an ADL, and so the following
candidates are added:
d) 7 -> ADL
-- OR is performed and 2 is selected as the best match

foo<int,int>();
-- no new namepsaces added, so no ADL
-- (even though 6 is a non-templt exact match and OL at POI would have
added this)
-- 3 is selected

foo<int,A::R>();
-- new candidates added due to ADL:
d) 0 // from A
e) 1 // from A
f) 5 // from A
g) 7 // from B
-- OR is performed and 3 is selected again (I think)

foo<int,R>();
-- new candidates added due to ADL:
d) 7 // from B
e) 6 // from global namespace
f) 8 // from global namespace
-- OR selects 8 (since non-template exact match)


I think there are some more interesting scenarios lurking in the above
example...
but, anyways, as I was saying, ADL is performed both at POD and POI.
OL is only performed at POD.

Of course I could be wrong, since I'm still figuring this stuff out.

Any comments or corrections are welcome.

regards,
-Faisal Vali

Daveed Vandevoorde

unread,
Jun 24, 2003, 10:02:47 PM6/24/03
to
fv...@eecs.ku.edu (faisal vali) wrote:
[... POD = point of definition ]

> I think there are some more interesting scenarios lurking in the above
> example...
> but, anyways, as I was saying, ADL is performed both at POD and POI.
> OL is only performed at POD.
>
> Of course I could be wrong, since I'm still figuring this stuff out.
>
> Any comments or corrections are welcome.

I didn't study your example, but your statement above it correct.

Daveed

Mirek Fidler

unread,
Jul 20, 2003, 5:27:12 AM7/20/03
to
|> > #include <vector>
|> > #include <algorithm>
|> > is different than
|> > #include <algorithm>
|> > #include <vector>
|> > Nifty, huh?

|> This starts to get scary.

> Starts? I consider myself probably better than average, and I'm
> totally incapable of understanding what happens in name lookup in
> templates more than half the time. I rather suspect that we've ended
> up with something so complicated that it cannot be safely used in real
> projects.

What about sweeping out all this dependent / non-dependent stuff and
return to method older/brokne compilers use anyway, that is deffering
everything to the point instatiation ?

I think that most problems w.r.t. templates are due to the fact that
as (perhaps) last minute change comitee decided that it would be a good
idea to check templates even when they are not instantiated. And perhaps
that it is bad that templates depened on order of declaration.

Well, I am not sure what problems were really solved. Templates
still depend on order of declarations. Compile time checking of
templates sometimes works, but not always.

I really had no problems using compilers that perform just
instatiation-point checks and resolutions. My problems started with
compilers that are compliant....

Mirek

Bo Persson

unread,
Jul 20, 2003, 6:04:17 AM7/20/03
to

""Mirek Fidler"" <c...@volny.cz> wrote...

> |> > #include <vector>
> |> > #include <algorithm>
> |> > is different than
> |> > #include <algorithm>
> |> > #include <vector>
> |> > Nifty, huh?

Only if vector references some of the algorithms without also
including <algorithm>. A nice library wouldn't do that, would it?

>
> |> This starts to get scary.
>
> > Starts? I consider myself probably better than average, and I'm
> > totally incapable of understanding what happens in name lookup in
> > templates more than half the time. I rather suspect that we've
ended
> > up with something so complicated that it cannot be safely used in
real
> > projects.
>
> What about sweeping out all this dependent / non-dependent stuff
and
> return to method older/brokne compilers use anyway, that is
deffering
> everything to the point instatiation ?

That just moves the "problem" to your implementation files. What if
*they* also include different headers?

Also, it is important for export that the compiler considers what is
visible in the template's implementation file.

>
> I think that most problems w.r.t. templates are due to the fact
that
> as (perhaps) last minute change comitee decided that it would be a
good
> idea to check templates even when they are not instantiated. And
perhaps
> that it is bad that templates depened on order of declaration.

So does other code. Even ordinary functions work differently depending
on the number of overloads visible.

Consider the functions std::abs() being declared in <complex>,
<cstdlib>, and several times in <cmath>. What happens to the call
abs(1.0) depends on which of these are visible...

Should we get rid of overloads as well?

>
> Well, I am not sure what problems were really solved. Templates
> still depend on order of declarations.

Not only templates!


Bo Persson
bo...@telia.com

Mirek Fidler

unread,
Jul 20, 2003, 8:14:12 AM7/20/03
to
> > What about sweeping out all this dependent / non-dependent stuff
> and
> > return to method older/brokne compilers use anyway, that is
> deffering
> > everything to the point instatiation ?
>
> That just moves the "problem" to your implementation files. What if
> *they* also include different headers?

Yeas, but I think I can rather handle this than all that
dependent/non-dependent names lookup complications....

I believe that without this, all chapter 14 would be reduced by 50%
and even moderately good programmer as me could finally use templates
without danger that more conforming C++ implementation will break all
his code again...

> Also, it is important for export that the compiler considers what is
> visible in the template's implementation file.

You mean that "export" that no compiler supported for 5 years after
the standard release and nobody ever needed ?!

> > Well, I am not sure what problems were really solved. Templates
> > still depend on order of declarations.
>
> Not only templates!

Hey, I agree with this. What I wanted to say is that if this problem
is present in other code, why in the world standard tries to be smarter
than is needed ?

Mirek

Gabriel Dos Reis

unread,
Jul 20, 2003, 5:23:30 PM7/20/03
to
c...@volny.cz ("Mirek Fidler") writes:

| I think that most problems w.r.t. templates are due to the fact that
| as (perhaps) last minute change comitee decided that it would be a good
| idea to check templates even when they are not instantiated. And perhaps
| that it is bad that templates depened on order of declaration.

I don't know where and when it started, I've been seeing confusion or
misinformation like the above being repeated more than often.

The notion of 2-phase name lookup was already considered in the dark
ages. The main difference with what was considered at the time is
that now not just operators may be dependent, but also functions used
in certain way and that in meantime we've got Argument Dependent Name
Lookup -- characterizing ADL as a "template baby" is a good recipe for
confusion.

At the time they were speaking of "bound symbols" (roughly what we call
"dependent name" nowadays), and "free symbols" ("non-dependent name"
in contemporary terms). Free symbols were supposed to be resolved in
the context of the template definition, and the bound symbols were
supposed to be resolved in the instantiation context.

http://anubis.dkuug.dk/jtc1/sc22/wg21/docs/papers/1992/N0209.ps

I find the above mentioned paper very instructive on understanding
what were the general design criteria and the philophical basis.

--
Gabriel Dos Reis, g...@integrable-solutions.net

---

Mirek Fidler

unread,
Jul 21, 2003, 1:54:44 AM7/21/03
to
> | I think that most problems w.r.t. templates are due to the fact
that
> | as (perhaps) last minute change comitee decided that it would be a
good
> | idea to check templates even when they are not instantiated. And
perhaps
> | that it is bad that templates depened on order of declaration.
>
> I don't know where and when it started, I've been seeing confusion or
> misinformation like the above being repeated more than often.

I must apologize, I do not know exact history. It is just it seems
so as it would be last minute change, given all chapter 14 content and
endless confusion about it...

Mirek

Gabriel Dos Reis

unread,
Jul 21, 2003, 2:32:24 PM7/21/03
to
c...@volny.cz ("Mirek Fidler") writes:

| > > Well, I am not sure what problems were really solved. Templates
| > > still depend on order of declarations.
| >
| > Not only templates!
|
| Hey, I agree with this. What I wanted to say is that if this problem
| is present in other code, why in the world standard tries to be smarter
| than is needed ?

I've seen no evidence that the "standard tires to be smarter
than is needed" as far as the template machinery is concerned. On the
other hand, I've seen repeated assertions with no technical foundation.

--
Gabriel Dos Reis, g...@integrable-solutions.net

---

Mirek Fidler

unread,
Jul 21, 2003, 4:34:27 PM7/21/03
to
> | Hey, I agree with this. What I wanted to say is that if this
problem
> | is present in other code, why in the world standard tries to be
smarter
> | than is needed ?
>
> I've seen no evidence that the "standard tires to be smarter
> than is needed" as far as the template machinery is concerned. On the
> other hand, I've seen repeated assertions with no technical
foundation.

What I wanted to say is that I do not see any advantage that
two-phase lookup would give to me as opposed to simple
instatiation-point lookup.

If there are any advantages I do not see yet, please go on and show
me them.

Mirek

ka...@gabi-soft.fr

unread,
Jul 23, 2003, 11:37:35 AM7/23/03
to
c...@volny.cz ("Mirek Fidler") wrote in message
news:<bff24j$du3fh$1...@ID-198693.news.uni-berlin.de>...

> > | I think that most problems w.r.t. templates are due to the
> > | fact that as (perhaps) last minute change comitee decided that it
> > | would be a good idea to check templates even when they are not
> > | instantiated. And perhaps that it is bad that templates depened on
> > | order of declaration.

> > I don't know where and when it started, I've been seeing confusion
> > or misinformation like the above being repeated more than often.

> I must apologize, I do not know exact history. It is just it seems
> so as it would be last minute change, given all chapter 14 content and
> endless confusion about it...

I guess it depends on what you mean by "last minute change". Chapter 14
didn't get its final wording into very late in the game. That doesn't
mean that nothing in it was discussed or considered earlier. It does
mean that compiler implementors couldn't get started earlier, with the
results that even today, no two compilers seem to implement exactly the
same thing. (As Gaby correctly points out, a lot of the changes are due
to the addition of namespaces. Let's face it, no one had any concrete
experience of how namespaces would work with two phase lookup in
templates, given that both were complete innovations by the committee,
so some experimentation was necessary.)

It's probably worth pointing out that most of the discussion outside of
the committee centered on all of the new things you could do with
standard C++. Two phase lookup doesn't add any new functionality, so it
didn't get any lead articles in C++ Report. Even today, I suspect that
most older programmers first learn about it when it hits them. This is
a shame, but I don't see what could have been done about it.

--
James Kanze GABI Software mailto:ka...@gabi-soft.fr
Conseils en informatique orientée objet/ http://www.gabi-soft.fr
Beratung in objektorientierter Datenverarbeitung
11 rue de Rambouillet, 78460 Chevreuse, France, +33 (0)1 30 23 45 16

Mirek Fidler

unread,
Jul 23, 2003, 3:02:58 PM7/23/03