8

What's the rationale of Koenig lookup?

Cannot avoid thinking of it like something that makes your code a lot harder to read and more instable.

Couldn't they define Koenig lookup so that it only work for specific cases (ie: non-member operators) or when explicitly required?

TylerH
  • 20,799
  • 66
  • 75
  • 101
peoro
  • 25,562
  • 20
  • 98
  • 150

2 Answers2

5

The original motivation, IIRC, was to be able to write

std::cout << 42;

without having to qualify std::operator<<(std::ostream&, int) explicitely.

If you want to disable argument dependant lookup, you can explicitely qualify the function name, ie. use std::swap instead of swap to prevent swap to be looked up in whatever namespace its arguments would live.

ADL can also be used with SFINAE to test at compile time whether some function is defined for a particular type (I'll let you work this out as an exercise, there is at least one question about this on Stackoverflow).

Alexandre C.
  • 55,948
  • 11
  • 128
  • 197
  • I think SFINAE has been conceived after ADL was introduced. My point anyway is that I'd like to be forced to explicitly say what namespace to use (or to explicitly say to apply ADL). ...I was explaining a piece of code I wrote to a friend of mine who doesn't talk C++; after I spent ten minutes talking about namespaces he asked me why, in my piece of code, I could use a function from another namespace without making it explicit. I sounded pretty much like "oh, well, yeah, because C++ has also got this other rule that ..." – peoro Jan 05 '11 at 10:12
  • @peoro: C++ has a lot of weird rules, and this is going to be worse with C++0x. However, I think ADL is best avoided by explicitly calling member functions with `this->` and using explicit qualifications whenever it makes sense. Most of the time, you don't need this (except with member function calls). And there are times when ADL is great. – Alexandre C. Jan 05 '11 at 10:16
  • @Alexandre C.: Yes, I know it can be avoidid that way, but that doesn't answer why ADL exists. I thought (this is a my personal opinion, yes) it would have been simpler and cleaner not to have it, and being forced to _avoid_ it. In what cases is it great? At the moment I'm seeing it like a weird rule of C++ that could be easily avoided in a language with a good syntax. – peoro Jan 05 '11 at 10:22
  • @peoro: As long as some people (Stroustrup ?) imagined it was cool to "left bitwise shift an ostream by something" to print a value (instead of, say, a print function), and some other people imagined it was cleaner to have namespaces, ADL was the "simplest" solution. It is, I confess, a dirty thing, but I'm afraid you'll have to deal with it (and with many other arcane C++ stuff that hit you in the foot if you don't know them, like exception safety, virtual destructors, static objects, overloaded new and delete, dangling references, you want a complete list ?) – Alexandre C. Jan 05 '11 at 10:31
  • @Alexandre C.: Eheh, no thanks, I've already enough of C++ syntax ;-) I was hoping there was some motivation different from the C++ syntax mess, but well, I'm not surprised... – peoro Jan 05 '11 at 10:41
  • 1
    It's not just for `operator<<`. Think of the `std::complex` class, which has overloaded arithmetic operators. Or all the various matrix libraries. It is pretty much essential for operators to be useful *at all*. Of course, it's less necessary for functions., but even there it can be convenient (as @Charles Bailey mentions in his answer, for selecting the correct `swap` function) – jalf Jan 05 '11 at 12:45
3

The strongest use case for ADL is for cases like this.

namespace A
{
    struct S {};
    S operator+( const S&, const S& );
}

namespace B
{
    A::S test()
    {
        A::S a, b;
        return a + b;
    }
}

It is also useful for selecting the correct swap function in generic code so it shouldn't only apply to operator functions. It is already a fairly complex part of the standard, making rules that prevented it from working in some cases would add further complexity, what would be the gain?

I can't think of any neat way of asking for it explicitly that would be significantly less verbose than calling a function in a different namespace directly and would, in any case, make expressions more complex.

We're you thinking something like: return [[ use_adl ]] (a + b); vs. return A::operator+( a, b ); ?

Péter Török
  • 114,404
  • 31
  • 268
  • 329
CB Bailey
  • 755,051
  • 104
  • 632
  • 656
  • 1
    Actually I was thinking to add some sort of keyword inside the function that use koenig lookup: `void f(const T &a) { namespaceof(T)::...; }` ... – peoro Jan 05 '11 at 09:53
  • 2
    @peroro: `namespaceof(T)` very much sounds like you are specifying a particular namespace to look up in; in which case you don't need ADL at all. You may as well use qualified id. – CB Bailey Jan 05 '11 at 09:55
  • @Charles Bailey: Yeah but then my question is still there. Wouldn't it be simpler (for compilers and for the standard) and cleaner (for programmers and for the standard) to have an operator like `namespaceof` instead of ADL, and being forced to explicitly use namespace? – peoro Jan 05 '11 at 10:15
  • Simpler for implementers, yes; cleaner for programmers, no. Can you imagine fully qualifiying `std::cout << a + b / c << mystr << '\n'` where each entity is not in the current namepace? It would be an unreadable mess (IMHO). – CB Bailey Jan 05 '11 at 10:23