friend, template, namespace

  • 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.


:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: