- A+
I want to have a templated friend function. However, I do not know how to make it works in the same way for no templated function. Here is a sample code
#include <iostream> namespace ns{ struct Obj { friend void foo(Obj){std::cout << "no problem" << std::endl;} template<typename T> friend void bar(Obj){std::cout << "problem" << std::endl;} }; } int main() { ns::Obj obj; foo(obj); // Compile bar<int>(obj); // Not compile return 0; }
Before C++20, you need to teach the compiler that bar
is the name of a template so that it knows that <
starts a template argument list and is not the less-than operator:
template<char> void bar() = delete; int main() { ns::Obj obj; foo(obj); // Compile bar<int>(obj); // Now compiles too return 0; }
Note that all the bar
overload has to do is to be a function template. The signature doesn't matter as long as it's not so good as to interfere with the overload resolution; ()
is a good choice because by definition we are passing at least one argument, so a function template taking no parameters can never be viable.
Alternatively, you can redesign bar
to deduce T
from a tag argument:
template<class T> struct type {}; namespace ns{ struct Obj { // ... template<typename T> friend void bar(Obj, type<T>) { /* ... */ } }; } // ... bar(obj, type<int>()); // OK
In C++20, the compiler will assume that bar
names a template when it sees the <
and name lookup finds nothing, so your code will just work.