473,698 Members | 2,445 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Why koenig lookup?

The so-called koenig lookup allows doing odd things like this:

#include <algorithm>
#include <string>

int main()
{
std::string table[10];
sort(table, table+10);
}

(Notice how the 'sort' doesn't have the std:: prefix, yet it's
perfectly valid.)

I understand that the reason for the koenig lookup to exist is so that
you can write things like:

std::cout << 5;

This is actually equivalent to:

operator<<(std: :cout, 5);

The koenig lookup allows the compiler to look for operator<< inside
the std namespace because one of the parameters is from that namespace.

With operators it makes sense. However, why perform the same lookup
for *all* functions? What's the advantage? Couldn't it be simply defined
that the koenig lookup is performed for operators but not for regular
functions?
Aug 9 '08
16 1651
kwikius wrote:
Jerry Coffin wrote:
>In article <2a0f00c3-10cd-4b64-8203-57c5e681b565
@k13g2000hse.g ooglegroups.com >, ja*********@gma il.com says...

[ ... ]
>>But doesn't use sin in a dependent context in a dependent
context in the template. I was thinking of the classical case,
where the operator<< for std::vector<int defined in global
namespace doesn't get found when it is used in
std::ostream_ iterator. Curiously, I can't reproduce the
symptomes in a simple example, but I've definitely had the
problem myself, and people post it here from time to time.

Here's a fairly simple example:

#include <map>
#include <string>
#include <iostream>
#include <algorithm>

typedef std::map<std::s tring, ints_int;

//namespace std {
std::ostream &operator<<(std ::ostream &os, s_int::value_ty pe const &v)
{ return os << v.first << ": " << v.second;
}

//}

int main() { s_int m;

m["a"] = 123;
m["b"] = 345;

std::copy(m.beg in(), m.end(),
std::ostream_i terator<s_int:: value_type>(std ::cout, "\n"));

return 0;
}

As it stands right now, it won't compile -- but remove the two comment
delimiters so operator<< is in namespace std, and it compiles and
works just fine.

Lemme guess. operator<<(std: :ostream&, int ) is ***NOT*** in global
namespace Right? .. Which is the whole point!

I'm with Alf Steinbach on this one....

regards
Andy Little
Oh I see..

hmm C++ is too complicated. Bring back BASIC I say :-(

regards
Andy Little
Aug 11 '08 #11
Alf P. Steinbach wrote:
* kwikius:
>kwikius wrote:
>>Jerry Coffin wrote:
In article <2a0f00c3-10cd-4b64-8203-57c5e681b565
@k13g2000hse .googlegroups.c om>, ja*********@gma il.com says...

[ ... ]

But doesn't use sin in a dependent context in a dependent
context in the template. I was thinking of the classical case,
where the operator<< for std::vector<int defined in global
namespace doesn't get found when it is used in
std::ostrea m_iterator. Curiously, I can't reproduce the
symptomes in a simple example, but I've definitely had the
problem myself, and people post it here from time to time.

Here's a fairly simple example:

#include <map>
#include <string>
#include <iostream>
#include <algorithm>

typedef std::map<std::s tring, ints_int;

//namespace std {
std::ostre am &operator<<(std ::ostream &os, s_int::value_ty pe const &v)
{ return os << v.first << ": " << v.second;
}

//}

int main() { s_int m;

m["a"] = 123;
m["b"] = 345;

std::copy(m.beg in(), m.end(),
std::ostream _iterator<s_int ::value_type>(s td::cout, "\n"));

return 0;
}

As it stands right now, it won't compile -- but remove the two
comment delimiters so operator<< is in namespace std, and it
compiles and works just fine.
Lemme guess. operator<<(std: :ostream&, int ) is ***NOT*** in global
namespace Right? .. Which is the whole point!

I'm with Alf Steinbach on this one....

Oh I see..

hmm C++ is too complicated. Bring back BASIC I say :-(

Well, the rule's simple: if you place an overload in the original
namespace, it will most likely be considered by original code there,
otherwise it may not.

It's like this:

#include <math.h>

namespace james
{
struct BigInt {};
double sin( BigInt ) { return 0; }
void foo() { sin( 3.14 ); } // *\/o
}

int main()
{
james::foo();
}

Here the sinful overload of sin placed in namespace james causes
compilation failure of foo. So I guess you're still with me on this...
Yes? <g>
Cheers,

- Alf
Well IIRC if you use VC8 then <cmathinclude s <math.hand then

using ::sin; etc

which is another situation again.

Anyway rather than discussing what does happen and why, which AFAICS is
extremely complicated (I can't find a way to get Jerry Coffins example
to find the function in global to create an ambiguity, which AFAICS
means global namespace is not considered in that case... whatever that
case actually is), I'm more interested in figuring out not even how to
fix it in C++, but if there is a simple solution to connecting a set of
UDT's to their correct expression generically(in my fictional
programming language 'Bob')

...and meanwhile in the real world I've had to bite the bullet and start
getting to grips with Latex... no not that sort. the Knuth, Tex latex..

http://miktex.org/

.... cool !

but I'm with you in spirit...

regards
Andy Little

Aug 11 '08 #12
On Aug 11, 3:37 am, "Alf P. Steinbach" <al...@start.no wrote:
* kwikius:
[...]
Well, the rule's simple: if you place an overload in the
original namespace, it will most likely be considered by
original code there, otherwise it may not.
Are you sure of that?
It's like this:

#include <math.h>

namespace james
{
struct BigInt {};
double sin( BigInt ) { return 0; }
void foo() { sin( 3.14 ); } // *\/o
}
int main()
{
james::foo();
}
Here the sinful overload of sin placed in namespace james
causes compilation failure of foo. So I guess you're still
with me on this... Yes? <g>
Yes. Good example of why 1) build-in types should be associated
with global namespace (rather than no namespaces) and 2)
functions which manipulate built-in types should be in global
namespace:-). (Your example doesn't involve ADL, but name
hiding. And it would work *IF* the argument of sin triggered
ADL. The problem here is that ADL doesn't apply to built in
types.)

Note that I'm not really arguing that ADL is a good thing per
se, but rather that it is not the real problem. Rather, the
fact that we need it is a symptom of a problem elsewhere; if we
just dropped it, without changing the way namespaces worked,
we'd be in worse shape than we are now.

--
James Kanze (GABI Software) email:ja******* **@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientier ter Datenverarbeitu ng
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Aug 11 '08 #13
The koenig lookup allows the compiler to look for operator<< inside
the std namespace because one of the parameters is from that namespace.

With operators it makes sense. However, why perform the same lookup
for *all* functions? What's the advantage? Couldn't it be simply defined
that the koenig lookup is performed for operators but not for regular
functions?
Here is a good (but quite long) article which explain this :
http://www.gotw.ca/publications/mill02.htm

--
Sebastien
Aug 11 '08 #14
On Aug 11, 8:04*am, "Alf P. Steinbach" <al...@start.no wrote:
* Alf P. Steinbach:

I now think I/we? have been blaming the wrong guy, ADL.

The whole thing about global namespace operator<< overload problem, beingjust a
case of name hiding.
what is the best solution for the operator<< example presented above?
I runned into the same problem once and I putted my operator<< inside
std:: as a quick non-std solution :-(

Diego
HP
Aug 11 '08 #15
On Aug 11, 8:10 pm, Diego Martins <jose.di...@gma il.comwrote:
On Aug 11, 8:04 am, "Alf P. Steinbach" <al...@start.no wrote:
* Alf P. Steinbach:
I now think I/we? have been blaming the wrong guy, ADL.
The whole thing about global namespace operator<< overload
problem, being just a case of name hiding.
what is the best solution for the operator<< example presented
above? I runned into the same problem once and I putted my
operator<< inside std:: as a quick non-std solution :-(
You mean overloading operator<< for something like
std::vector<dou ble>? The best solution is not to do it, at all.
What happens if a collegue is also using std::vector<dou ble>,
and also wants to overload<< for it?

What you want is a type with known semantics, or rather, with a
known standard display format. In mathematics, for example,
you'd almost certainly have a Vector class, with various
additional operators not supported by std::vector<dou ble>.
Unless it was a Polynome class. In exceptional cases where you
really do have a raw std::vector, you can create a small
decorator class which does the trick:

template< typename T >
class AsVector // mathematical vector...
{
public:
explicit AsVector( std::vector< T const& v )
: myV( v )
{
}
friend std::ostream&
operator<<( std::ostream& dest,
AsVector const& source ) ;

private:
std::vector< T const&
myV ;
} ;

template< typename T >
inline AsVector< T >
asVector( std::vector< T const& v )
{
return AsVector< T >( v ) ;
}

AsPolynome would be similar, except that the code for the
operator<< would be very different.

--
James Kanze (GABI Software) email:ja******* **@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientier ter Datenverarbeitu ng
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Aug 12 '08 #16
"Alf P. Steinbach" <al***@start.no wrote in message
news:Cc******** *************** *******@posted. comnet...
I don't think Andrew Koenig, or /anyone else/, fully grokked the
consequences at the time.
Well, that kind of depends.

First, let me emphasize that I did not invent the idea of argument-dependent
lookup, nor was I particularly fond of the idea. The main reason my name
got hung on it was that I played a significant role in convincing the
standards committee that something like it was necessary.

The examples that show the need to find operators are too well known for me
to need to elaborate them further. The examples that are the real killers,
however, come up when we start using templates. Consider:

template <class Tvoid foo(T t1, T t2) {
// ...
T t3 = t1 + t2;
T t4 = combine(t1, t2);
// ...
};

I hope you will agree with me that it would not be a good thing if there
were no way to decide where to look up the + in t1 + t2. But if you agree
there, then what can we say about looking up "combine" in combine(t1, t2)?
Shouldn't it be possible to write

namespace Mine {
class Thing { /* ... */ };
Thing operator+(Thing , Thing);
Thing combine(Thing, Thing);
// ...
}

and then call foo(Mine::Thing (), Mine::Thing())?

If it's necessary for foo to be able to find Mine::operator+ by looking at
the type of t1 and t2, isn't it equally necessary for foo to be able to find
Mine::combine for the same reason? Notice that in both cases, there is *no*
way for the author of foo to specify a namespace explicitly, because the
author of foo has no way of knowing what namespace to specify.

This problem first came to my attention pretty late in the standardization
process, and I realized that if the standard as it then stood were to be
approved, neither t3 nor t4's initializing expression would be able to be
compiled. So I explained the problem to the committee, mentioned that if we
didn't do anything about it, we would be faced with a lot of pretty obvious
programs that would not compile, and it was pretty much a matter of going
with the best we could come up with in the time available or revising the
schedule.

I don't recall having an opinion at the time about which was the better
course of action. However, it is now more than ten years later, and I don't
seem to see a consensus on a better solution to the problem--which suggests
that perhaps delaying the standard wouldn't have made things any better.

So I guess it comes down to which consequences I grokked. What I did know
is that we had discovered a very serious problem, that we did not know a
perfect solution, and that we had to do *something*. Short of reworking all
the name lookup rules from scratch, it's far from clear to me what other
alternatives we had.
Aug 25 '08 #17

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

Similar topics

1
1610
by: Dave | last post by:
#include <iostream> using std::cout; using std::endl; // #define CAUSE_ERROR namespace N { struct foo_t {};
11
1704
by: REH | last post by:
I'm a little confused about argument dependent lookup. Exactly when does this apply? Specifically, I was hoping to use it to access enumeration constants. For example: namespace Flags { enum flag_type {F1, F2, F3}; } void foo(Flags::flag_type f) {
2
1926
by: Jean-Louis Leroy | last post by:
I'm trying to compile the following code with gcc (version below). I would expect the compile to try the operator ==() declared in Tangram::Backend because of Koenig lookup. But it doesn't happen. Is it me or the compiler? namespace Tangram { namespace Backend { struct RELATIONAL;
3
2915
by: my-wings | last post by:
I've been reading about how evil Lookup fields in tables are, but I've got to be missing something really basic. I know this subject has been covered before, because I've just spent an hour or two reading about it on google, but there is something I still don't understand, and I'm hoping someone will be willing to explain it to me in small words. Let's say I have a table for addresses, and it includes a field for state. What I would...
3
10651
by: google | last post by:
I have a database with four table. In one of the tables, I use about five lookup fields to get populate their dropdown list. I have read that lookup fields are really bad and may cause problems that are hard to find. The main problem I am having right now is that I have a report that is sorted by one of these lookup fields and it only displays the record's ID number. When I add the source table to the query it makes several records...
3
1223
by: REH | last post by:
I'm a little confused about argument dependent lookup. Exactly when does this apply? Specifically, I was hoping to use it to access enumeration constants. For example: namespace Flags { enum flag_type {F1, F2, F3}; } void foo(Flags::flag_type f) {
5
2343
by: Javier Estrada | last post by:
I'm using a user-defined diagnostics stream and custom manipulators that work with it template<class charT, class traits = std::char_traits<charT> class basic_diagsstream : public std::basic_ostream<charT, traits ... } and a manipulator
2
2045
by: cgv | last post by:
Hi, I want to distinguish between an int parameter to a template function depending on whether its value is known at compile time or not. For the compile time version I want to call the function with the syntax func<5>(); and for the dynamic version with
2
2123
by: Peng Yu | last post by:
Hi, I'm wondering if Koenig lookup can be applied somehow to derive which template to use based on the template arguments. The following code shows an example where multiply_traits's namespace A has to be specified in the definition of Y. This makes Y unusable for any multiply_traits defined in other namespaces, which corresponding T1 and T2 defined in those namespaces. See also comments in the code.
0
8675
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
9029
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
1
8897
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
8862
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
0
7729
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
0
5860
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
4370
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
2
2331
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
3
2002
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

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

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