|
Introduction
With the release of Everett looming, it's probably timely for some articles to be written on some of the 'new' features that are finally making it into Microsoft's C++ compiler. By new, I of course mean the things that every compiler since CFront has had, barring Visual C++. Nevertheless, they say it's better late than never, and so at last we are to have full Koenig lookup. So what is it ?
The standard
Let's start with what the standard says, always a good place to start.
When an unqualified name is used as the postfix-expression in a function call, other namespaces not considered during the usual unqualified lookup may be searched, and namespace-scope friend function declarations not otherwise visible may be found. These modifications to the search depend on the types of the arguments...
So what does this mean ? It means that if I call a function, and pass in a parameter that lives in a namespace, that namespace becomes a valid place for the compiler to look for that function. Why do we have such a rule ? Let's consider how it's likely to be used.
What is an interface ?
The most common assumption is that an interface is the list of methods which are exposed by an object, those found in its header file. However, this is not all there is to it. If I have a class called Bar(), and I want to insert it into an ostream, I would write a method that looks like this: template<class charT, class Traits>
std::basic_ostream<charT, Traits> &
operator << (std::basic_ostream<charT, Traits> & os, const Bar & b)
{
return os;
}
Is this a method on the public interface of the Bar class ? No. Is it part of the interface that Bar offers ? Most certainly. Without Bar, it is of no use to anyone, it wouldn't even compile without it. I'd like you to keep this example in mind as I show you an example of Koenig lookup, taken direct from the C++ standard. namespace NS
{
class T { };
void f(T){};
}
NS::T parm;
int main()
{
f(parm);
};
In this example, a namespace is created, which contains a class and a function. Replace NS with std, and f with the inserter above and you'll see how it could exist in real life. Now we create an instance of NS::T, and then in our main function, we call the f method. What Koening lookup says is this:
When a function is called, in order to determine if that function is visible in the current scope, the namespaces in which the functions parameters reside must be taken into account.
So even though f is in theory hidden ( add a function called f in the namespace that takes an int, and if you try to call it from main, it will fail to compile), Koenig lookup says the function is visible because you have an instance of an object which exists in that namespace, and which is a parameter to the function.
So how did the old compiler versions work ?
If we need Koenig lookup to write stream operators, etc., then how did it work in the past ? I'm not sure of the implimentation details, but the net result was that Koenig lookup only worked for operators, while straight functions, like the one in our example, did not work. Which in theory covered about 90% of the ways most people would use Koenig lookup, but also allowed you to write code which VC6/7 would compile, but a conforming C++ compiler would not. For example: namespace NS
{
class T { };
void f(T){};
}
NS::T parm;
void f(T){};
int main()
{
f(parm);
};
This should not compile, because the call to f() is ambiguous. Under VC.NET and VC6 it compiles fine, because Koenig lookup fails.
More broken code
Here is an example of code that equally fails to compile in all compilers, just to keep the playing ground level: namespace NS1
{
class T1 {};
}
namespace NS2
{
class T2 {};
void f(NS1::T1, T2) {};
}
namespace NS1
{
void f(T1, NS2::T2) {};
}
NS1::T1 t1;
NS2::T2 t2;
int main()
{
f(t1,t2);
}
Thanks to whoever brought this up in the questions ( can't see them right now ). An earlier VC version simply cannot see ANY function named f. Add one to the global namespace, and it would call that. Everett, and every other compiler I know of, will complain that there are two functions visible with the same prototype. Passing int1 makes the function in NS1 visible to the global namespace, and passing in T2 makes the function in NS2 visible. Koenig lookup is being applied twice here.
To reiterate
I have had quite a few complaints with regard to this article, so I apologise if I am hammering the one simple point over and over, I don't get paid by the word, I just want everyone to 'get it'. Here is the standard example fleshed out to include a real class, and a real operator. #include <iostream>
using std::cout;
using std::cin;
namespace NS
{
struct Date
{
int m_nYear, m_nMonth, m_nDay;
Date::Date() : m_nYear(1969), m_nMonth(2), m_nDay(17)
{
}
};
template<class charT, class Traits>
std::basic_ostream<charT, Traits> &
operator << (std::basic_ostream<charT, Traits> & os, const Date & d)
{
os << d.m_nDay << "-" << d.m_nMonth << "-" << d.m_nYear;
return os;
}
}
int main()
{
NS::Date d;
cout << d << " is my birthday, so buy me lots of loot";
int i;
cin >> i;
}
This code defines a struct for holding a date, for simplicity the members are public. The iostream inserter is badly written, also for simplicity. Read my article if you want to know how to write good ones. The thing with this example is that if I ask 'how does the compiler know how to call the inserter', the answer seems obvious, it has to. It's part of the interface. Yes, but it's also a function that is not part of the class, and is hidden in a namespace. By now I hope you know that the reason the operator is visible is Koenig lookup. This example would probably compile on VC6 and 7 ( I cannot test it ), because as I said before, operators have always worked. However, the change is that now all code, including the example we pulled from the standard, will use Koenig lookup to decide which namespaces to search to find a function to call.
Conclusion
To be honest, I'd regard examples like the one in the standard with caution. I can't think of a real world use for Koenig lookup outside of the sort of thing that compiled on previous versions of the Microsoft C++ compiler. However, I don't think that is the point. It's a bit hard to learn what cool things you can do with a language feature if that feature is not supported in your compiler. The fact that it was possible to write code on previous versions of VC which ( correctly ) won't compile in the next release is just one more reason that this change is long overdue. I look forward to finding new and exciting uses for Koenig lookup, and I hope you do as well.
Version 1.1
In response to the small percentage of people who felt that this was as clear as mud, I have added a couple of extra examples and some more explanation. I'd appreciate feedback as to if this clarifies things for you all.
| You must Sign In to use this message board. |
|
| | Msgs 1 to 25 of 66 (Total in Forum: 66) (Refresh) | FirstPrevNext |
|
|
 |
|
|
That "should not compile" example:
namespace NS { class T { }; void f(T){}; }
NS::T parm;
void f(T){};
int main() { f(parm); };
Car is missing the declaration or introduction of T in the outer namespace in order to make the [void f(T){};] compilable, and only then could one discuss the matching.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
To be honest, I'd regard examples like the one in the standard with caution. I can't think of a real world use for Koenig lookup outside of the sort of thing that compiled on previous versions of the Microsoft C++ compiler.
In case you're interested, I recently had an annoying problem with the lack of full Koening support in connection with my bimap class. This class lives inside namespace codeproject and provides a global function codeproject::swap for efficient swapping (std::swap, in contrast, performs in worse-than-linear time). In standard C++, this should work;bimap<int,int> bm1; bimap<int,int> bm2; ... swap(bm1,bm2); // calls codeproject::swap But unfortunately, it is std::swap that is used here, so there's no choice but to explicitly qualify the function:bimap<int,int> bm1; bimap<int,int> bm2; ... codeproject::swap(bm1,bm2); This example is merely annoying, but the problem has no cure with generic code like this:template <class container_type> void f(container_type& c1,container_type& c2) { ... swap(c1,c2); ... } Regards,
Joaquín M López Muñoz Telefónica, Investigación y Desarrollo
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Cool. So there it is, a real life example that KL is useful in all cases.
Christian
No offense, but I don't really want to encourage the creation of another VB developer. - Larry Antram 22 Oct 2002
C# will attract all comers, where VB is for IT Journalists and managers - Michael P Butler 05-12-2002
Again, you can screw up a C/C++ program just as easily as a VB program. OK, maybe not as easily, but it's certainly doable. - Jamie Nordmeyer - 15-Nov-2002
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
No, scratch that - it was good, now it's better. It's something i've never needed to know, and, possibly never will, but if i do then now i will, vs. a day spent cursing my compiler. Nice job.
---
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
I understood everything plainly... but I still can't think of a time when I've never needed to use Koenig lookup. I guess if you use iostreams a lot, it can be helpful. But are there any other good examples, besides iostreams, of this actually being useful? Just curious, I've awlays been one to try to incorporate esoteric language features into my code. 
Even a broken clock is right twice a day.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
If anything, you need a well defined lookup that ALL standard compilers follow. The standard committee chose this method.
Tim Smith
I'm going to patent thought. I have yet to see any prior art.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
I agree with that, although I'll say that I've never had the need for any lookup methods beyond just looking up in the current namespace or specifying a namespace explicitly.
Even a broken clock is right twice a day.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
NOTE: for the record, I still ranked the article high, becuase it was quite informative. I was just hoping for more real-world examples. 
Even a broken clock is right twice a day.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
That's cool, you should rate it as you see it, that tells me when people like or don't like. I appreciate your rating.
The truth is that the example I have now added ( and previously referred to ) is, as I say in the article, the only real world example I can think of, and it worked under the old compiler. Time will tell if cool uses of this can be found, but I don't see how, it's a pretty basic and non-flexible rule.
Christian
No offense, but I don't really want to encourage the creation of another VB developer. - Larry Antram 22 Oct 2002
C# will attract all comers, where VB is for IT Journalists and managers - Michael P Butler 05-12-2002
Again, you can screw up a C/C++ program just as easily as a VB program. OK, maybe not as easily, but it's certainly doable. - Jamie Nordmeyer - 15-Nov-2002
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Hey!
I've got a litle question about the Koenig Lookup.
namespace NS1 { class T1 {/*...*/}; void f(T1, NS2::T2) {/*...*/}; } namespace NS2 { class T2 {/*...*/}; void f(NS1::T1, T2) {/*...*/}; } NS1::T1 t1; NS2::T2 t2; int main() { f(t1,t2); //... }
Which one will be called, NS1::f or NS2::f ? Or compiler will report an error?
Ñ There is only one MP Ð
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
I'll go with compiler error, but I'm going to try it to be sure and incorperate it into the changes I am about to make. In this case, I am sure you'd need to scope the functions manually, they look the same to the compiler.
Christian
No offense, but I don't really want to encourage the creation of another VB developer. - Larry Antram 22 Oct 2002
C# will attract all comers, where VB is for IT Journalists and managers - Michael P Butler 05-12-2002
Again, you can screw up a C/C++ program just as easily as a VB program. OK, maybe not as easily, but it's certainly doable. - Jamie Nordmeyer - 15-Nov-2002
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Without testing, my money is on NS2 as the Koenig standard doesn't specificially prohibit respecification. prove me wrong. 
Regardz Colin J Davies
Sonork ID 100.9197:Colin
You are the intrepid one, always willing to leap into the fray! A serious character flaw, I might add, but entertaining. Said by Roger Wright about me.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
I did - I put it in and it complained about multiple functions.
Christian
No offense, but I don't really want to encourage the creation of another VB developer. - Larry Antram 22 Oct 2002
C# will attract all comers, where VB is for IT Journalists and managers - Michael P Butler 05-12-2002
Again, you can screw up a C/C++ program just as easily as a VB program. OK, maybe not as easily, but it's certainly doable. - Jamie Nordmeyer - 15-Nov-2002
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
 |
|
|
I'm getting really depressed.
Alvaro Mendez wrote: I know it's not a simple topic to explain
I'm afraid that in my mind, it's an incredibly simple topic, made simpler when explained in terms of it's motives ( an external function can be thought of as part of an interface ) and real world use ( iostreams being the most obvious example ).
Alvaro Mendez wrote: Maybe this article was just meant for a different breed of programmer.
I'm going to rework it now to see if I can't labour the point a little more.
Christian
No offense, but I don't really want to encourage the creation of another VB developer. - Larry Antram 22 Oct 2002
C# will attract all comers, where VB is for IT Journalists and managers - Michael P Butler 05-12-2002
Again, you can screw up a C/C++ program just as easily as a VB program. OK, maybe not as easily, but it's certainly doable. - Jamie Nordmeyer - 15-Nov-2002
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Christian Graus wrote: I'm going to rework it now to see if I can't labour the point a little more.
Thanks for your extra time and effort Christian. It has certainly payed off. It's now easier to comprehend what this whole Koenig thing is about from your article.
Regards, Alvaro
Well done is better than well said. -- Benjamin Franklin (I actually prefer medium-well.)
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
I'm with the majority - this article has taught me something I didn't know about C++ and I'm better off for it. Take 5 from me, and have a while you're at it.
Thanks for the article, and pay no attention to those who don't read before commenting.
-- Simon Steele Programmers Notepad - http://www.pnotepad.org/
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
If this article really gave you a good understanding of what Koenig Lookup is, then you're a better man than me. The only thing this article taught me was that Christian is capable of writing much better articles and decided not to in this case, for some reason. To learn about Koenig I had to do a Google search -- see my post above.
Regards, Alvaro
Well done is better than well said. -- Benjamin Franklin (I actually prefer medium-well.)
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Respectfully, it appears that most people have been able to work out what I was trying to say. However, this article was written late at night, in response to the low percentage of people who ticked 'Koenig lookup' in the poll of features they knew how to use, and I am about to rework it a little to try and help those who find it confusing, or think it's about the .NET IDE.
Christian
No offense, but I don't really want to encourage the creation of another VB developer. - Larry Antram 22 Oct 2002
C# will attract all comers, where VB is for IT Journalists and managers - Michael P Butler 05-12-2002
Again, you can screw up a C/C++ program just as easily as a VB program. OK, maybe not as easily, but it's certainly doable. - Jamie Nordmeyer - 15-Nov-2002
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
I agree with Jörgen - this article contains factual information about C++, not just opinions. Maybe it should be called a "Tutorial", but that is up to Chris to put it in proper place.
Thanks, Christian!
Best wishes, Hans
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Thanks for the support. Yes, I don't think this is where it should be, but I could not find a better place to put it in the wizard. I assume it will be moved when it is edited.
Christian
No offense, but I don't really want to encourage the creation of another VB developer. - Larry Antram 22 Oct 2002
C# will attract all comers, where VB is for IT Journalists and managers - Michael P Butler 05-12-2002
Again, you can screw up a C/C++ program just as easily as a VB program. OK, maybe not as easily, but it's certainly doable. - Jamie Nordmeyer - 15-Nov-2002
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
hi CG,
I really appreciate your effort on this. Though I wouldn't tell that I understand it completely ('cause i'm not able to think of a situation where i can use this facility in my daily prog. tasks, may be its for those who write those programming libraries like boost et al), it was definitely informative, atleast now I know what they are talking about when they mention these topics. Did you by chance go through the c++ standards, I have never gone through it, can't digest more than two sentences at a time  Probably you should ask Chris to open up a different section, was surprised to find it in samples. Since you have made a article on this one, probably you can add one on PTS 
regards Kannan
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Kannan Kalyanaraman wrote: Did you by chance go through the c++ standards, I have never gone through it, can't digest more than two sentences at a time
No, I read Stroustrup cover to cover, but I cannot digest the standard either.
Kannan Kalyanaraman wrote: Since you have made a article on this one, probably you can add one on PTS
I hope to, in the next few days. Also one on all of the other features being added, most of which are even simpler than KL.
Christian
No offense, but I don't really want to encourage the creation of another VB developer. - Larry Antram 22 Oct 2002
C# will attract all comers, where VB is for IT Journalists and managers - Michael P Butler 05-12-2002
Again, you can screw up a C/C++ program just as easily as a VB program. OK, maybe not as easily, but it's certainly doable. - Jamie Nordmeyer - 15-Nov-2002
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
There is a forum for VS.NET IDE issues, where you could raise your point. Do not misuse the article posting to express your views.
> This should not compile, because the call to f() is > ambiguous. Under VC.NET and VC6 it compiles fine, because > Koenig lookup fails.
What makes it ambiguous?
Best regards, Paul.
Jesus Christ is LOVE! Please tell somebody.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Paul Selormey wrote: There is a forum for VS.NET IDE issues, where you could raise your point. Do not misuse the article posting to express your views.
How is this a misuse? It's an article just like any other. Sure, it's not a "here's the code, use it if you want" article, but it's still article material. How many C++ programmers on CP do you think know about the Koenig lookup?
Paul Selormey wrote: What makes it ambiguous?
Exactly.
-- Only in a world this sh***y could you even try to say these were innocent people and keep a straight face.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
General News Question Answer Joke Rant Admin
|