7

How does this work? Is it related to ADL?

#include <iostream>

template <typename T>
struct A
{
    friend void f(T x)
    {
        std::cout << "A\n";
    }
};

int main()
{
    f(new A<void*>());
}

Can somebody tell me why i can't use something like

f(A<int>());
jogojapan
  • 68,383
  • 11
  • 101
  • 131
FrozenHeart
  • 19,844
  • 33
  • 126
  • 242
  • Having the word `friend` in a definition isn't right IIRC. – chris Sep 05 '12 at 04:29
  • @JesseGood, Ah, found it. I must be thinking of something else. I recall something like that having a blatantly obvious statement in the standard against it. – chris Sep 05 '12 at 04:36
  • @chris: Yes, lookup "friend name injection" and you will get a bunch of hits. It used to be the case that the name was visible in namespace scope, but the rules changed so that the function can only be accessed using ADL. – Jesse Good Sep 05 '12 at 04:43
  • 1
    I have corrected the Markdown. In the original version `` was interpreted as HTML tag, so it appeared as if you were asking why `f(A())` (rather than `f(A())`) does not work. – jogojapan Sep 05 '12 at 05:01
  • BTW this class is unsafe. calling f(new A()) and then f(new A()) results in a double definition error of f. – Johannes Schaub - litb Nov 30 '12 at 09:37

1 Answers1

13
f(new A<void*>());    

Indeed works because of Argument dependent lookup/Koenig lookup(ADL)
Koenig Lookup states:

You don’t have to qualify the namespace(scope) for functions if one or more argument types are defined in the namespace of the function.

Consider a simplistic example not using templates and it should help you understand ADL at work better:

#include <iostream>
struct A
{
    friend void f(A x)
    {
        std::cout << "A\n";
    }
};

int main()
{
    f(A());
    return 0;
}

Output:

A

When you use f(A<int>()), it mandates that f() requires an argument of the type int, but your structure does not provide any conversion from A to int and hence the error.

If you provide the appropriate conversion then it will work as well. Something like:

operator int(){return 1;}
Community
  • 1
  • 1
Alok Save
  • 202,538
  • 53
  • 430
  • 533