This time the compiler complaints that he can't find any 'doFoo' at all.
And if i declare the doFoo outside the class, i get the reasonable mismatched types error. Seems like the "friend ..." part is just being ignored.

So is there a problem with my understanding? What is the difference between a function and an operator in this case?

Notice how at least one argument of operator* must be a Num<T>. This is not the case for doFoo. Your type could be constructible from int without T being int itself. The fun is that it still wouldn't work if your converting constructors had a correspondence to the template arguments of the class template. You cannot deduce a class template argument through a member function of that template. You can get around that by providing a make_num function.
–
pmrNov 19 '12 at 11:50

3 Answers
3

the compiler has no way of finding foo, given an int parameter. This would be the equivalent of calling your friend operator like this:

Num<int> n = 5 * 10;

This will "work", but not by calling the friend operator* defined in your Num class, but by calling the built-in operator* for integers, and then using the implicit conversion from Num's converting constructor.

This is not really the reason, you can reproduce the same issue removing the template and thus the template argument. The answer is how lookup finds (or fails to find) friend declarations.
–
David Rodríguez - dribeasNov 19 '12 at 12:52

@DavidRodríguez-dribeas OK, that makes sense. So it is ADL, and it fails because the argument is not in the class namespace.
–
juanchopanzaNov 19 '12 at 12:55

Kind of. It is ADL, but it does not have anything to do with the namespace where this is defined. Lookup will only find a friend declaration through ADL, but we are not talking about adding a namespace into the search, but the type. While most people think of ADL as bringing the namespace of the arguments in, it does more than that: it looks for declarations that are only available inside the types of the arguments, which is the case here.
–
David Rodríguez - dribeasNov 19 '12 at 13:01

The core problem is lookup. A friend declaration provides a declaration of a namespace level function, but the declaration is only available inside the class that is befriending it. In the example the book provides that is not an issue: the function takes two arguments of the enclosing type, as long as one of them is of the enclosing type, Argument Dependent Lookup will look inside the definition of the class and find the operator. In your case that is not the case, since there is a single argument and that needs a conversion, the compiler will not look inside the definition of the class.

This cannot be done for a template (and for all instantiating types) as the friend declaration is a declaration of a non-templated function. Although you could can play with the code just for the sake of testing: