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 

Koenig lookup hides ordinary function
Goto page 1, 2, 3, 4  Next
 
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ Language (Moderated)
View previous topic :: View next topic  
Author Message
Khoguan Phuann
Guest





PostPosted: Fri Jul 29, 2005 1:15 am    Post subject: Koenig lookup hides ordinary function Reply with quote



I have been searching for Koenig lookup examples on the Net.
Though many of them were found, none of them seems to address
the following situation:

#include <vector>

int distance(std::vector<int> v1, const std::vector<int> v2)
{
return v1.size() - v2.size();
}

int main()
{
std::vector<int> v1(3), v2(1);
int distance(std::vector<int> v1, std::vector<int> v2);
int d = distance(v1, v2);
return 0;
}

The error messages from gcc 3.4.4 or on-line Comeau vaguely
hint that the distance() function template from STL is chosen
instead of the user-defined ordinary function with the same
name.

In this example, does Koenig lookup have higher priority over
the ordinary lookup, i.e. the latter never comes into play?
Or have the ordinary lookup actually been done but other further
rules excluded the locally declared and globally defined distance()
function? If ordinary lookup has really been considered, then the
two distance() functions should become overload candidates and
the user-defined ordinary function with exact match of arguments
should have been chosen rather than the function template. Right?

This is Comeau's diagnostics:

"stl_iterator_base.h", line 110: error:
class "std::vector<int, std::allocator" has no
member "iterator_category"
typedef typename _Iterator::iterator_category iterator_category;
^
detected during instantiation of class
"std::iterator_traits<_Iterator>
[with _Iterator=std::vector<int, std::allocator]"
at line 12 of "ComeauTest.c"
------------------------------------
Thanks a lot for your kind enlightenment.

Khoguan Phuann


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

Back to top
tpochep@mail.ru
Guest





PostPosted: Fri Jul 29, 2005 9:51 am    Post subject: Re: Koenig lookup hides ordinary function Reply with quote



Hallo.

Khoguan Phuann писал(а):

Quote:
I have been searching for Koenig lookup examples on the Net.
Though many of them were found, none of them seems to address
the following situation:

#include <vector

int distance(std::vector {
return v1.size() - v2.size();
}

int main()
{
std::vector<int> v1(3), v2(1);
int distance(std::vector<int> v1, std::vector<int> v2);
int d = distance(v1, v2);
return 0;
}

It's not a Koenig lookup problem. Ordinary lookup can find you specific
distance. ADL (or Koenig lookup)
can find std::distance (you need first #include <algorithm>). Overload
resolution selects std::distance, and
here is an error, because vector is not an iterator.


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


Back to top
tpochep@mail.ru
Guest





PostPosted: Fri Jul 29, 2005 9:52 am    Post subject: Re: Koenig lookup hides ordinary function Reply with quote



In your example ordinary lookup finds your specific distance, and
Koenig lookup
finds std::distance. But std::distance is:

template <class InputIterator>
typename iterator_traits<InputIterator>::difference_type
distance(InputIterator first, InputIterator last);

so, compilation fails here (trying to instantiate iterator_traits with
std::vector<int>).

This is simplified version of your code:

namespace STD
{
class A{};
template<class T>
struct Traits
{
typedef typename T::type type;
};

template<class T>
typename Traits<T>::type fun(T &t){}
}

void fun(STD::A){}

int main()
{
STD::A a;
void fun(STD::A);
fun(a);
}

If we modify code

#include <iostream>

namespace STD
{
class A{};
template<class T>
void fun(T){std::cout<<"from STDn";}
}

void fun(STD::A)
{
std::cout<<"Globaln";
}

int main()
{
void fun(STD::A);
STD::A a;
fun(a);//compiler has two functions, but it selects non-template
(C++ rule)
}


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

Back to top
Jason Hise
Guest





PostPosted: Fri Jul 29, 2005 11:05 am    Post subject: Re: Koenig lookup hides ordinary function Reply with quote

I suspect that the fact that your global distance function takes a
const vector for its second argument may be influencing things. Does
the same thing happen when that const is removed, or when you pass an
actual constant vector for the second argument?


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

Back to top
Rob Williscroft
Guest





PostPosted: Fri Jul 29, 2005 12:47 pm    Post subject: Re: Koenig lookup hides ordinary function Reply with quote

Khoguan Phuann wrote in news:1122581987.748379.43930
@g14g2000cwa.googlegroups.com in comp.lang.c++.moderated:

Quote:
#include <vector

int distance(std::vector {
return v1.size() - v2.size();
}

int main()
{
std::vector<int> v1(3), v2(1);
int distance(std::vector<int> v1, std::vector<int> v2);
int d = distance(v1, v2);
return 0;
}

The error messages from gcc 3.4.4 or on-line Comeau vaguely
hint that the distance() function template from STL is chosen
instead of the user-defined ordinary function with the same
name.

In this example, does Koenig lookup have higher priority over


ADL (Argument Dependant Lookup, what you call Koenig lookup)
finds std::distance, and since it is an exact match it is selected
in preference to your ::distance.

The probem here is that <vector> has included a declaration for
std::distance (which its allowed to do) and that the container
std::vector is declared in the same namespace as the alogorithm
std::distance which it isn't designed to work with.

Its a bug in the specification of the Standard library (*) that we
have to live with and the only fix is to make either a qualified
call to your distance function or to forbid ADL:

int main()
{
std::vector<int> v1(3), v2(1);
int d = ::distance(v1, v2); /* qualified */
d = (distance)(v1, v2); /* ADL forbiden */
}

*) The Standard Library was AIUI specifed (and part of the draft
standard) *before* Andrew Koenig invented ADL.

Rob.
--
http://www.victim-prime.dsl.pipex.com/

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


Back to top
Tom Widmer
Guest





PostPosted: Fri Jul 29, 2005 12:48 pm    Post subject: Re: Koenig lookup hides ordinary function Reply with quote

I think this might indicate a widespread compiler bug. By my reckoning,
your global function should be chosen, since template argument
deduction should fail for std::distance

"Type deduction may fail for the following reasons:
[...]
- Attempting to use a type in the qualifier portion of a qualified
name that names a type when that type does not contain the specified
member, or if the specified member is not a type where a type is
required."

That leaves only one function to call (which is found by ordinary
lookup), and that is your distance function, so it should be called
unambiguously. Perhaps someone can point out the flaw in my reasoning,
since it does seem unlikely that VC7.1, GCC 3.4 and Comeau C++ all
share this "bug"!

Tom


[ 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: Fri Jul 29, 2005 1:45 pm    Post subject: Re: Koenig lookup hides ordinary function Reply with quote

Khoguan Phuann wrote:
Quote:
I have been searching for Koenig lookup examples on the Net.
Though many of them were found, none of them seems to address
the following situation:

There's no Koenig lookup involved here.

Quote:
#include <vector

int distance(std::vector {
return v1.size() - v2.size();
}

int main()
{
std::vector<int> v1(3), v2(1);
int distance(std::vector<int> v1, std::vector<int> v2);
int d = distance(v1, v2);
return 0;
}

The error messages from gcc 3.4.4 or on-line Comeau vaguely
hint that the distance() function template from STL is chosen
instead of the user-defined ordinary function with the same
name.

In this example, does Koenig lookup have higher priority over
the ordinary lookup, i.e. the latter never comes into play?

Not that I know of. In fact, I would have thought that, having
found a function declaration at block scope, no functions at
namespace scope would be taken into account, Koenig lookup or
not. This would seem to be covered by 3.3.7/1. On the other
hand, 3.4.2 doesn't seem to allow any exceptions, so maybe it
is the intent that std:: also be brought into play. Given that,
however, the locally declared function should still participate
in overload resolution, and given that it is an exact match, I
can hardly see why it wouldn't be chosen.

Quote:
Or have the ordinary lookup actually been done but other
further rules excluded the locally declared and globally
defined distance() function? If ordinary lookup has really
been considered, then the two distance() functions should
become overload candidates and the user-defined ordinary
function with exact match of arguments should have been chosen
rather than the function template. Right?

One would hope so.

There is an exception for dependant names in a template, but
that shouldn't apply here.

--
James Kanze GABI Software
Conseils en informatique oriente objet/
Beratung in objektorientierter Datenverarbeitung
9 place Smard, 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
Alf P. Steinbach
Guest





PostPosted: Fri Jul 29, 2005 1:46 pm    Post subject: Re: Koenig lookup hides ordinary function Reply with quote

* Khoguan Phuann:
Quote:
I have been searching for Koenig lookup examples on the Net.
Though many of them were found, none of them seems to address
the following situation:

#include <vector

int distance(std::vector {
return v1.size() - v2.size();
}

int main()
{
std::vector<int> v1(3), v2(1);
int distance(std::vector<int> v1, std::vector<int> v2);
int d = distance(v1, v2);
return 0;
}

The error messages from gcc 3.4.4 or on-line Comeau vaguely
hint that the distance() function template from STL is chosen
instead of the user-defined ordinary function with the same
name.

I reproduced the error with on-line Comeau and MSVC 7.1 using the following
"corrected" code:

#include <vector>

int distance(
std::vector<int> const& v1, std::vector<int> const& v2
)
{
return static_cast<int>( v1.size() - v2.size() );
}

int main()
{
std::vector<int> v1(3), v2(1);
int d = distance(v1, v2);
return 0;
}


Quote:
In this example, does Koenig lookup have higher priority over
the ordinary lookup, i.e. the latter never comes into play?

Koenig lookup is applied, because the name 'distance' is unqualified.

The additional results of Koenig lookup don't have higher priority.

Quoting 3.4.2/2: "If the ordinary unqualified lookup of the name finds the
declaration of a class member function, the associated namespaces and
classes are not considered. Otherwise the set of declarations found by the
lookup of the function name is the union of the set of declarations found
using ordinary lookup and the set of declarations found in the namespaces
and classes associated with the argument types."

So, only in the case where a class member function is found does the
ordinary lookup have priority.

I wonder why that priority was so restricted.


Quote:
Or have the ordinary lookup actually been done but other further
rules excluded the locally declared and globally defined distance()
function?

They're on equal footing.


Quote:
If ordinary lookup has really been considered, then the
two distance() functions should become overload candidates and
the user-defined ordinary function with exact match of arguments
should have been chosen rather than the function template. Right?

There is the question, yes, but I don't know the answer.

However, it seems that now three compilers, namely gcc, msvc and comeau,
agree that the function template is the best match, and that SFINAE rules
(substitution failure is not an error) don't apply -- whatever the details
of them are, exactly.

With my current understanding I think this -- that ordinary lookup doesn't
have priority in general, only for class member functions -- should be
corrected, because when only the compiler can figure out what's going on for
a simple function call, the language rules are just plain wrong. However,
it may be that someone explains why that restriction to class member
functions was put in there, and that the explanation makes good sense. In
that case my fallback opinion (Wink) is that _something_ should be corrected.

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?

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


Back to top
Gianluca Silvestri
Guest





PostPosted: Fri Jul 29, 2005 1:50 pm    Post subject: Re: Koenig lookup hides ordinary function Reply with quote


<tpochep (AT) mail (DOT) ru> ha scritto nel messaggio
news:1122626681.306893.51300 (AT) g43g2000cwa (DOT) googlegroups.com...
Quote:
In your example ordinary lookup finds your specific distance, and
Koenig lookup
finds std::distance. But std::distance is:

template <class InputIterator
typename iterator_traits distance(InputIterator first, InputIterator last);

so, compilation fails here (trying to instantiate iterator_traits with
std::vector<int>).

I can't understand why SFINAE doesn't kick in. If the compiler can't
instantiate the template function with those parameters, why does'nt it
simply remove the template from the set of overloaded functions. ?

Can you explain this, please?

Thanks,
Gianluca


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


Back to top
Gianluca Silvestri
Guest





PostPosted: Fri Jul 29, 2005 1:51 pm    Post subject: Re: Koenig lookup hides ordinary function Reply with quote


"Rob Williscroft" <rtw (AT) freenet (DOT) co.uk> ha scritto nel messaggio
news:Xns96A27DC56B203rtwfreenetREMOVEcouk (AT) 216 (DOT) 196.109.145...
Quote:
Khoguan Phuann wrote in news:1122581987.748379.43930
@g14g2000cwa.googlegroups.com in comp.lang.c++.moderated:

#include <vector

int distance(std::vector {
return v1.size() - v2.size();
}

int main()
{
std::vector<int> v1(3), v2(1);
int distance(std::vector<int> v1, std::vector<int> v2);
int d = distance(v1, v2);
return 0;
}

The error messages from gcc 3.4.4 or on-line Comeau vaguely
hint that the distance() function template from STL is chosen
instead of the user-defined ordinary function with the same
name.

In this example, does Koenig lookup have higher priority over


ADL (Argument Dependant Lookup, what you call Koenig lookup)
finds std::distance, and since it is an exact match it is selected
in preference to your ::distance.

if your remove the const on the second parameter of the OP's distance() you

obtain a perfect match but still I got the error. Do you why?

Thanks,
Gianluca


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


Back to top
Rob Williscroft
Guest





PostPosted: Fri Jul 29, 2005 3:59 pm    Post subject: Re: Koenig lookup hides ordinary function Reply with quote

Gianluca Silvestri wrote in news:v6qGe.17577$2U1.1161413 (AT) news3 (DOT) tin.it in
comp.lang.c++.moderated:

Quote:
| > int distance(std::vector<int> v1, const std::vector<int> v2)
| > {
| > return v1.size() - v2.size();
| > }
|
| > int main()
| > {
| > std::vector<int> v1(3), v2(1);
| > int distance(std::vector<int> v1, std::vector<int> v2);
| > int d = distance(v1, v2);
| > return 0;
| > }
|

|
| ADL (Argument Dependant Lookup, what you call Koenig lookup)
| finds std::distance, and since it is an exact match it is selected
| in preference to your ::distance.
|
if your remove the const on the second parameter of the OP's
distance() you obtain a perfect match but still I got the error. Do
you why?


Sorry, I perhapse wasn't clear enough in the above paragraph.

If *any* viable function is found by ADL then functions that
could be found by ordinary lookup aren't considered unless
they are also found by ADL.

In the above case ADL only looks in namespace std (as the
class-template vector is decared there) and nowhere else.
So it only adds std::distance<> to the overload set.
std::distance< std::vector< int > > failes to compile and
a diagnostic is produced.

Also the const applied to non-reference paramiter doesn't
affect the signature of the function as far as overload
resolution is conserned. It only affects wether or not the
argument is treated as const *within* the body of the function.

Rob.
--
http://www.victim-prime.dsl.pipex.com/

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


Back to top
Tom Widmer
Guest





PostPosted: Fri Jul 29, 2005 5:40 pm    Post subject: Re: Koenig lookup hides ordinary function Reply with quote

It's a perfect match even if you don't remove the const - top level
cv-qualifiers on function parameter types are ignored during overload
resolution.

Tom


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

Back to top
Alf P. Steinbach
Guest





PostPosted: Fri Jul 29, 2005 5:41 pm    Post subject: Re: Koenig lookup hides ordinary function Reply with quote

* Rob Williscroft:
Quote:
Gianluca Silvestri wrote in news:v6qGe.17577$2U1.1161413 (AT) news3 (DOT) tin.it in
comp.lang.c++.moderated:

| > int distance(std::vector<int> v1, const std::vector<int> v2)
| > {
| > return v1.size() - v2.size();
| > }
|
| > int main()
| > {
| > std::vector<int> v1(3), v2(1);
| > int distance(std::vector<int> v1, std::vector<int> v2);
| > int d = distance(v1, v2);
| > return 0;
| > }
|

|
| ADL (Argument Dependant Lookup, what you call Koenig lookup)
| finds std::distance, and since it is an exact match it is selected
| in preference to your ::distance.
|
if your remove the const on the second parameter of the OP's
distance() you obtain a perfect match but still I got the error. Do
you why?


Sorry, I perhapse wasn't clear enough in the above paragraph.

If *any* viable function is found by ADL then functions that
could be found by ordinary lookup aren't considered unless
they are also found by ADL.

In the above case ADL only looks in namespace std (as the
class-template vector is decared there) and nowhere else.
So it only adds std::distance<> to the overload set.
std::distance< std::vector< int > > failes to compile and
a diagnostic is produced.

Quoting 3.4.2/2: "If the ordinary unqualified lookup of the name finds the
declaration of a class member function, the associated namespaces and
classes are not considered. Otherwise the set of declarations found by the
lookup of the function name is the union of the set of declarations found
using ordinary lookup and the set of declarations found in the namespaces
and classes associated with the argument types."

Note: "union".

I don't find your rule, and the above seems to contradict it?

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?

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


Back to top
Rob Williscroft
Guest





PostPosted: Fri Jul 29, 2005 5:42 pm    Post subject: Re: Koenig lookup hides ordinary function Reply with quote

Rob Williscroft wrote in news:Xns96A2A52C853A7rtwfreenetREMOVEcouk@
216.196.109.145 in comp.lang.c++.moderated:

Quote:
If *any* viable function is found by ADL then functions that
could be found by ordinary lookup aren't considered unless
they are also found by ADL.


Why I would think the above is true, I can't imagine. I've read
the relevent portions of the standard several times, clearly
though, not yet enough times for it to actually sink in ;-(.

Rob.
--
http://www.victim-prime.dsl.pipex.com/

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


Back to top
Rob Williscroft
Guest





PostPosted: Fri Jul 29, 2005 5:48 pm    Post subject: Re: Koenig lookup hides ordinary function Reply with quote

Khoguan Phuann wrote in news:1122581987.748379.43930
@g14g2000cwa.googlegroups.com in comp.lang.c++.moderated:

Quote:

#include <vector

int distance(std::vector {
return v1.size() - v2.size();
}

int main()
{
std::vector<int> v1(3), v2(1);
int distance(std::vector<int> v1, std::vector<int> v2);
int d = distance(v1, v2);
return 0;
}

The error messages from gcc 3.4.4 or on-line Comeau vaguely
hint that the distance() function template from STL is chosen
instead of the user-defined ordinary function with the same
name.



Having got this wrong once (or twice) I'll have another go,

The problem isn't that std::distance is being choosen above
::distance, but that overload resolution failes to complete.

Here's the declaration for std::distance:

template<class InIt> inline
typename iterator_traits<InIt>::difference_type
distance( InIt First, InIt Last);

Before overload resoution can proceed, the compiler tries to
instantiate this (declaration!) with InIt = std::vector< int >.

Inorder to do that it needs to temporarily instantiate
std::iterator_traits< std::vector< int > >, this unsuprisingly
fails and a diagnostic is produced.

Alas this isn't a substitution failure, had iterator_traits
instantiated but lacked the type(def) member difference_type,
that would be a substitution failure. I.e. the substitution
would compile but *fail* to provide a valid type where one
was expected.

Rob.
--
http://www.victim-prime.dsl.pipex.com/

[ 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, 3, 4  Next
Page 1 of 4

 
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.