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 

problem with Koenig lookup ?
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
Bronek Kozicki
Guest





PostPosted: Sun Sep 21, 2003 6:54 pm    Post subject: problem with Koenig lookup ? Reply with quote



following snippet has been recently posted on pl.comp.lang.c :

1 template <typename T>
2 struct A
3 {
4 friend void f(A<T>&) { }
5 };
6
7 template <typename T>
8 struct P
9 {
10 P()
11 {
12 t_ = new T();
13 }
14
15 ~P()
16 {
17 f(*t_);
18 }
19
20 T * t_;
21 };
22
23 int main()
24 {
25 P< A p;
26 }

It compiles sucesfully on GCC 3.2.3 and MSVC71. However, after
commenting out line 12 both compilers are throwing error:

(MSVC71)
C:WINGNUmsys1.0homebronislawT93.cpp(17) : error C3861: 'f':
identifier not found, even with argument-dependent lookup
C:WINGNUmsys1.0homebronislawT93.cpp(16) : while compiling
class-template member function 'P<T>::~P(void)'
with
[
T=A<int>
]
C:WINGNUmsys1.0homebronislawT93.cpp(25) : see reference to
class template instantiation 'P<T>' being compiled
with
[
T=A<int>
]

(GCC 3.2.3)
C:/WINGNU/msys/1.0/home/bronislaw/T93.cpp: In destructor `P<T>::~P() [with T =
A<int>]':
C:/WINGNU/msys/1.0/home/bronislaw/T93.cpp:25: instantiated from here
C:/WINGNU/msys/1.0/home/bronislaw/T93.cpp:17: `f' undeclared (first use this
function)
C:/WINGNU/msys/1.0/home/bronislaw/T93.cpp:17: (Each undeclared identifier is
reported only once for each function it appears in.)

I think that code is fine (Comeau compiles it sucesfully), and error is
due to incomplete Koenig lookup. Or am I wrong ?


B.


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
Ralf Schneeweiß
Guest





PostPosted: Mon Sep 22, 2003 6:37 pm    Post subject: Re: problem with Koenig lookup ? Reply with quote



I think, this has nothing to do with the Koenig lookup.

Quote:
1 template <typename T
2 struct A
3 {
4 friend void f(A

You can not define a method within a friend-declaration.

Quote:
5 };

Am I wrong?

Ralf

www.oop-trainer.de



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

Back to top
Bronek Kozicki
Guest





PostPosted: Mon Sep 22, 2003 10:39 pm    Post subject: Re: problem with Koenig lookup ? Reply with quote



On 22 Sep 2003 14:37:17 -0400, Ralf Schneeweiß wrote:
Quote:
You can not define a method within a friend-declaration.
Am I wrong?

I think that you are wrong, see clause 11.4 , par. 5. Can we talk about
Koenig lookup now (or any other possible cause of compiler error) ?


B.

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

Back to top
Emil Dotchevski
Guest





PostPosted: Mon Sep 22, 2003 10:44 pm    Post subject: Re: problem with Koenig lookup ? Reply with quote

The reason is that the member object t_ is a pointer, and so its
definition is fine with an incomplete A<T>, therefore the compiler has
no reason to instantiate A<T>, and you end up without f.

Obviously not instantiating templates that are not strictly needed is
a key feature of C++. But I am not sure what the standard says about
this particular case.

--Emil

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





PostPosted: Mon Sep 22, 2003 10:44 pm    Post subject: Re: problem with Koenig lookup ? Reply with quote

Ralf Schneeweiß wrote:
Quote:
I think, this has nothing to do with the Koenig lookup.

1 template <typename T
2 struct A
3 {
4 friend void f(A
You can not define a method within a friend-declaration.

You cannot. First of all because C++ has no methods. The second is that
teh only known definiton of method coming from Bjarne Stroustrup from TC++PL
says something like: some people call virtual member functions methods. But
you can define a function (non-member) in a friend declaration. According
to my knowledge it is a quite old trick to use it for friend declarations
inside templates and it has been "revived" on the first The C++ Seminar (
http://www.thecppseminar.com ) in a speech by Dan Saks entitled "Making New
Friends".

Quote:
5 };

Am I wrong?

Apparently. AFAIU the above creates a new "standalone" friend function for
every instantiation of the A class template. In addition as my
understanding of the standard went about a 18 monts ago the created function
will be a freestanding function but *inside* the scope of the class. The
only reason it will be found is Koenig lookup. Gurus, please correct me if
I am wrong.

--
WW aka Attila



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

Back to top
Chris Newton
Guest





PostPosted: Tue Sep 23, 2003 11:12 am    Post subject: Re: problem with Koenig lookup ? Reply with quote

Emil Dotchevski wrote...
Quote:
The reason is that the member object t_ is a pointer, and so its
definition is fine with an incomplete A<T>, therefore the compiler has
no reason to instantiate A<T>, and you end up without f.

But ~P< A calls f(A<int>&), and thus should ideally instantiate
the appropriate specialisation of f at that point.

Is your argument that this is a circular problem: f(A<int>&) hasn't yet
been instantiated at that point, so it can't be found by Koenig lookup,
but since it can't be found, it doesn't need to be instantiated?

If so, I think the catch is that although f(A<int>&) hasn't been
instantiated, it should still be considered by Koenig look-up just as
any other name in a suitable scope would be. In this case, isn't f
technically within the class scope of A<int>, and thus a candidate?

If so, then as the only candidate that matches the call to f, that name
should be chosen. Now according to 14.7.1/2, the required specialisation
of f should be implicitly instantiated at that point. Curiously, I don't
think any instantiation of A<int> itself is required however.

Cheers,
Chris


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

Back to top
johnchx
Guest





PostPosted: Tue Sep 23, 2003 11:16 am    Post subject: Re: problem with Koenig lookup ? Reply with quote

[email]emild (AT) collectivestudios (DOT) com[/email] (Emil Dotchevski) wrote

Quote:
Obviously not instantiating templates that are not strictly needed is
a key feature of C++. But I am not sure what the standard says about
this particular case.

14.7.1/1 says:

...the class template specialization is implicitly instantiated
when the specialization is referenced in a context that requires
a completely-defined object type or when the completenes of the
class type affects the semantics of the program.

My reading would be that the completeness of the class seems to affect
the semantics of the program in this case, so the compiler should
implicitly instantiate A<int>.

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

Back to top
Emil Dotchevski
Guest





PostPosted: Wed Sep 24, 2003 11:36 am    Post subject: Re: problem with Koenig lookup ? Reply with quote

Quote:
But ~P< A calls f(A<int>&), and thus should ideally instantiate
the appropriate specialisation of f at that point.

But to call a function that takes A<int> &, you do not need to
instantiate A<int>. In fact, it is wrong to instantiate A<int>, as a
complete definition may not be available. Consider this:

template <class>
class A;

void foo( A<int> & );

void bar( A<int> & x )
{
foo( x );
}

The above code must (and does) compile as is, without the A template
being defined. If a call to a function that takes A<int> & required
the compiler to instantiate A<int>, then the above code would not
compile, and this would be rather unfortunate.

So, it makes perfect sence that the compiler does not instantiate the
template in the original example. And since it does not instantiate
the template, the f function never gets defined, and you get an error.

--Emil

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

Back to top
Peter Dimov
Guest





PostPosted: Wed Sep 24, 2003 10:25 pm    Post subject: Re: problem with Koenig lookup ? Reply with quote

[email]johnchx2 (AT) yahoo (DOT) com[/email] (johnchx) wrote in message news:<4fb4137d.0309221848.761dc0d9 (AT) posting (DOT) google.com>...
Quote:
emild (AT) collectivestudios (DOT) com (Emil Dotchevski) wrote

Obviously not instantiating templates that are not strictly needed is
a key feature of C++. But I am not sure what the standard says about
this particular case.

14.7.1/1 says:

...the class template specialization is implicitly instantiated
when the specialization is referenced in a context that requires
a completely-defined object type or when the completenes of the
class type affects the semantics of the program.

My reading would be that the completeness of the class seems to affect
the semantics of the program in this case, so the compiler should
implicitly instantiate A<int>.

An interesting requirement, with some interesting implications.

In the general case, the compiler cannot possibly know whether the
completeness of the class will affect the semantics of the program
without "instantiating" it first:

template<class T> struct A: public compute_base_class<T>::type
{
};

I put "instantiating" in quotes since this is not an ordinary
instantiation, which is allowed to fail the compilation if the
definition of A<int> is ill-formed.

If I read the comments for CWG issue #415:

http://std.dkuug.dk/jtc1/sc22/wg21/docs/cwg_active.html#415

correctly, it appears that such a "speculative instantiation" concept
was indeed discussed, but it's still unclear whether compilers are
expected to do that.

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

Back to top
tom_usenet
Guest





PostPosted: Wed Sep 24, 2003 10:35 pm    Post subject: Re: problem with Koenig lookup ? Reply with quote

On 21 Sep 2003 14:54:37 -0400, Bronek Kozicki <brok (AT) rubikon (DOT) pl> wrote:

Quote:
I think that code is fine (Comeau compiles it sucesfully), and error is
due to incomplete Koenig lookup. Or am I wrong ?

Section 14.6.5 describes the name injection of friends declared in
templates. The injection only occurs when the template in question is
instantiated, and the name is injected at the point of instantiation.
In your example, there is nothing that forces the instantiation of
A<int>, so IMHO, the lookup should fail.

As far why Comeau compiles it, well, perhaps my analysis is
incorrect...

Tom

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

Back to top
johnchx
Guest





PostPosted: Thu Sep 25, 2003 1:30 pm    Post subject: Re: problem with Koenig lookup ? Reply with quote

[email]pdimov (AT) mmltd (DOT) net[/email] (Peter Dimov) wrote
Quote:
johnchx2 (AT) yahoo (DOT) com (johnchx) wrote
14.7.1/1 says:

...the class template specialization is implicitly instantiated
when the specialization is referenced in a context that requires
a completely-defined object type or when the completenes of the
class type affects the semantics of the program.

My reading would be that the completeness of the class seems to affect
the semantics of the program in this case, so the compiler should
implicitly instantiate A<int>.

An interesting requirement, with some interesting implications.


Indeed.

Quote:
In the general case, the compiler cannot possibly know whether the
completeness of the class will affect the semantics of the program
without "instantiating" it first:

template<class T> struct A: public compute_base_class<T>::type
{
};

I put "instantiating" in quotes since this is not an ordinary
instantiation, which is allowed to fail the compilation if the
definition of A<int> is ill-formed.

If I read the comments for CWG issue #415:

http://std.dkuug.dk/jtc1/sc22/wg21/docs/cwg_active.html#415

correctly, it appears that such a "speculative instantiation" concept
was indeed discussed, but it's still unclear whether compilers are
expected to do that.

That's certainly one possibility.

Another alternative would be to re-word 14.7.1/1 to say "...or when
the completeness of the class type *could* affect the semantics of the
program," which would actually require the compiler to fail the
compilation if the instantiation was ill-formed.

Off the top of my head, I can only think of two contexts where this
comes up -- operator lookup and ADL. Since both of these would
involve an expression whose type *is* the template instantion in
question, I don't think we'd see the same kind of "spurious
instantiation" problems that we see with overload resolution.

Issue #416 also seems to bear on this:

http://std.dkuug.dk/jtc1/sc22/wg21/docs/cwg_active.html#416

In particular, Steve Adamczyk says:

There is a rule that will instantiate a class template in order to
be able to see whether it has any operators.

....which seems to imply full-fledged instantiation takes place whether
or not the operator in question is found in the instantiated class.

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

Back to top
Peter Dimov
Guest





PostPosted: Thu Sep 25, 2003 11:37 pm    Post subject: Re: problem with Koenig lookup ? Reply with quote

[email]johnchx2 (AT) yahoo (DOT) com[/email] (johnchx) wrote in message news:<4fb4137d.0309242043.666afb6f (AT) posting (DOT) google.com>...
Quote:
pdimov (AT) mmltd (DOT) net (Peter Dimov) wrote
In the general case, the compiler cannot possibly know whether the
completeness of the class will affect the semantics of the program
without "instantiating" it first:

template<class T> struct A: public compute_base_class<T>::type
{
};

I put "instantiating" in quotes since this is not an ordinary
instantiation, which is allowed to fail the compilation if the
definition of A<int> is ill-formed.

If I read the comments for CWG issue #415:

http://std.dkuug.dk/jtc1/sc22/wg21/docs/cwg_active.html#415

correctly, it appears that such a "speculative instantiation" concept
was indeed discussed, but it's still unclear whether compilers are
expected to do that.

That's certainly one possibility.

Another alternative would be to re-word 14.7.1/1 to say "...or when
the completeness of the class type *could* affect the semantics of the
program," which would actually require the compiler to fail the
compilation if the instantiation was ill-formed.

But this will break existing code.

Quote:
Off the top of my head, I can only think of two contexts where this
comes up -- operator lookup and ADL. Since both of these would
involve an expression whose type *is* the template instantion in
question, I don't think we'd see the same kind of "spurious
instantiation" problems that we see with overload resolution.

The template instantiation needs only be part of the type:

#include <iostream>

template<class T> struct A;

namespace N
{

template<class T> struct X
{
friend void f(typename A<T>::type)
{
std::cout << "X::fn";
}
};

} // namespace N

template {
};

template<class T> struct A
{
typedef Y< N::X type;
};

template<class T> void f(Y<T>)
{
std::cout << "::fn";
}

// template struct N::X
int main()
{
f( Y< N::X() );
}

I think I can obfuscate it even further but this is enough to illustrate the point.

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

Back to top
johnchx
Guest





PostPosted: Sat Sep 27, 2003 12:58 am    Post subject: Re: problem with Koenig lookup ? Reply with quote

[email]pdimov (AT) mmltd (DOT) net[/email] (Peter Dimov) wrote
Quote:
johnchx2 (AT) yahoo (DOT) com (johnchx) wrote
Another alternative would be to re-word 14.7.1/1 to say "...or when
the completeness of the class type *could* affect the semantics of the
program," which would actually require the compiler to fail the
compilation if the instantiation was ill-formed.

But this will break existing code.


Perhaps...though arguably it breaks existing, but ill-formed, code.
:-)

FWIW, the comeau compiler exhibits this behavior today, so at least
one implementor thinks that this is the rule already.

Quote:
Off the top of my head, I can only think of two contexts where this
comes up -- operator lookup and ADL. Since both of these would
involve an expression whose type *is* the template instantion in
question, I don't think we'd see the same kind of "spurious
instantiation" problems that we see with overload resolution.

The template instantiation needs only be part of the type:


You're right, of course.

Still, the instantiations that occur will have been "mentioned" --
directly or indirectly -- as template-ids in the type of the parameter
passed to the function, which, I think, offers less scope for spurious
instantiations than we see with overload resolution.

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

Back to top
Chris Newton
Guest





PostPosted: Sun Sep 28, 2003 1:58 am    Post subject: Re: problem with Koenig lookup ? Reply with quote

Emil Dotchevski wrote...
Quote:
But to call a function that takes A<int> &, you do not need to
instantiate A<int>.

Sure, taken in isolation obviously that's true.

But why do we need an instantiation of A<int> here anyway? It's whether
f(A<int>&) is defined that is important, isn't it?

Surely the instantiation of A<int> is only important if it's required
for the definition of f(A<int>&). If that is the case, then don't the
implicit instantiation rules cited in this thread imply that A<int> must
be instantiated at that point?

(There is a separate issue if we don't have the information available to
do that instantiation, but in this case, we do.)

Cheers,
Chris


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

Back to top
Peter Dimov
Guest





PostPosted: Mon Sep 29, 2003 10:03 pm    Post subject: Re: problem with Koenig lookup ? Reply with quote

[email]johnchx2 (AT) yahoo (DOT) com[/email] (johnchx) wrote in message news:<4fb4137d.0309252217.1eb244d4 (AT) posting (DOT) google.com>...
Quote:
pdimov (AT) mmltd (DOT) net (Peter Dimov) wrote
[email]johnchx2 (AT) yahoo (DOT) com[/email] (johnchx) wrote
Another alternative would be to re-word 14.7.1/1 to say "...or when
the completeness of the class type *could* affect the semantics of the
program," which would actually require the compiler to fail the
compilation if the instantiation was ill-formed.

But this will break existing code.


Perhaps...though arguably it breaks existing, but ill-formed, code.
:-)

FWIW, the comeau compiler exhibits this behavior today, so at least
one implementor thinks that this is the rule already.

Yep, I suspect that EDG wrote that part of the standard, but I'm still
not sure whether it really says what they wanted it to say, and
whether _we_ want it to say that. ;-)

Quote:
Off the top of my head, I can only think of two contexts where this
comes up -- operator lookup and ADL. Since both of these would
involve an expression whose type *is* the template instantion in
question, I don't think we'd see the same kind of "spurious
instantiation" problems that we see with overload resolution.

The template instantiation needs only be part of the type:


You're right, of course.

Still, the instantiations that occur will have been "mentioned" --
directly or indirectly -- as template-ids in the type of the parameter
passed to the function, which, I think, offers less scope for spurious
instantiations than we see with overload resolution.

Hm. For further consideration:

#include <iostream>

template<class T> struct Y
{
};

template<class T> struct X
{

friend void f(Y<T>)
{
std::cout << "X::fn";
}
};

template {
std::cout << "::fn";
}

// template struct X
int main()
{
f( Y<int>() );
}

The compilers disagree on this one, too. g++ 3.x/MSVC 7.1 say that the
explicit instantiation affects the outcome. Comeau/EDG consistently
choses ::f.

Another interesting example. This:

#include <iostream>

template<class T> struct Y
{
};

template<class T> struct X
{
typedef int T::* type;
};

template<class T> void f(Y<T>)
{
std::cout << "::fn";
}

int main()
{
f( Y< X() );
}

fails under Comeau. This, however, works:

#include <iostream>

template<class T> struct Y
{
};

template<class T> struct X;

template<class T> void f(Y<T>)
{
std::cout << "::fn";
}

int main()
{
f( Y< X() );
}

The "no instantiation" camp happily compiles both, of course.

[ 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.