When you call f(s) , you need to specify the template parameter S , because it cannot be inferred from the argument S
But if you change it to f<S>(s) (assuming that you intended to call it with the same argument of the S template that g was called from), you forbid ADL and the only way to define a friend function in the region class can be found ADL. Therefore, you need to add the declaration of f to the global namespace so that a call to g can find it.
So, to make it work, you need to add these declarations before Foo
template<typename T> class Foo; template<typename S, typename T> S f(const Foo<T> &); template<typename S, typename T> S g(const Foo<T> &);
and change the call in g to f<S>(s) or something else like f<x>(s)
source share