File: koenig.yo

package info (click to toggle)
c%2B%2B-annotations 13.02.02-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 13,576 kB
  • sloc: cpp: 25,297; makefile: 1,523; ansic: 165; sh: 126; perl: 90; fortran: 27
file content (75 lines) | stat: -rw-r--r-- 3,952 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
If emi(Koenig lookup) were called the `Koenig principle', it could have been
the title of a new i(Ludlum) novel. However, it is not. Instead it refers to
a bf(C++) technicality.

`Koenig lookup' refers to the fact that if a function is called without
specifying its namespace, then the namespaces of its argument types are used
to determine the function's namespace. If the namespace in which the argument
types are defined contains such a function, then that function is used. This
procedure is called the `Koenig lookup'.

As an illustration consider the next example. The function
tt(FBB::fun(FBB::Value v)) is defined in the tt(FBB) namespace. It
can be called without explicitly mentioning its namespace:
        verbinclude(-a examples/koenig1.cc)
    The compiler is rather smart when handling namespaces. If tt(Value) in the
tt(namespace FBB) would have been defined as tt(using Value = int) then
tt(FBB::Value) would be recognized as tt(int), thus causing the Koenig lookup
to fail.

    As another example, consider the next program. Here two namespaces are
involved, each defining their own tt(fun) function. There is no
ambiguity, since the argument defines the namespace and tt(FBB::fun) is
called:
        verbinclude(-a examples/koenig2.cc)

    Here is an example in which there em(is) an ambiguity: tt(fun) has two
arguments, one from each namespace. The ambiguity must be resolved by the
programmer:
        verbinclude(-a examples/koenig3.cc)

    An interesting subtlety with namespaces is that definitions in one
namespace may break the code defined in another namespace. It shows that
namespaces may affect each other and that namespaces may backfire if we're not
aware of their peculiarities. Consider the following example:
        verbinclude(-a examples/koenig4.cc)
    Whatever happens, the programmer'd better not use any of the functions
defined in the tt(ES) namespace, since that would result in infinite
recursion. However, that's not the point. The point is that the programmer
won't even be given the opportunity to call tt(ES::fun) since the compilation
fails.

    Compilation fails for tt(gun) but not for tt(fun). But why is that so? Why
is tt(ES::fun) flawlessly compiling while tt(ES::gun) isn't? In tt(ES::fun)
tt(fun(x)) is called. As tt(x)'s type is not defined in a namespace the Koenig
lookup does not apply and tt(fun) calls itself with infinite recursion.

    With tt(ES::gun) the argument is defined in the tt(FBB)
namespace. Consequently, the tt(FBB::gun) function is a possible candidate to
be called. But tt(ES::gun) itself also is possible as tt(ES::gun)'s prototype
perfectly matches the call tt(gun(x)).

    Now consider the situation where tt(FBB::gun) has not yet been
declared. Then there is of course no ambiguity. The programmer responsible for
the tt(ES) namespace is resting happily. Some time after that the programmer
who's maintaining the tt(FBB) namespace decides it may be nice to add a
function tt(gun(Value x)) to the tt(FBB) namespace. Now suddenly the code in
the namespace tt(ES) breaks because of an addition in a completely other
namespace (tt(FBB)). Namespaces clearly are not completely independent of each
other and we should be aware of subtleties like the above. Later in the
annotations() (chapter ref(OVERLOADING)) we'll return to this issue.

    em(Koenig lookup) is only used in the context of namespaces. If a function
is defined outside of a namespace, defining a parameter of a type that's
defined inside a namespace, and that namespace also defines a function with an
identical signature, then the compiler reports an ambiguity when that function
is called. Here is an example, assuming the abovementioned namespace tt(FBB)
is also available:
        verb(    void gun(FBB::Value x);

    int main(int argc, char **argv)
    {
        gun(FBB::Value{});          // ambiguity: FBB::gun and ::gun can both
                                    // be called.
    })