Friend 显式特化函数模板和 ADL

Friend explicit specialization of function template and ADL

为什么下面的偏特化没有被ADL选中?

template<class T>
void func1(T&){     // selected
    ...
}

namespace first{
    template<class R>
    struct foo{
       friend void func1<>(foo<R>&){        // expected
          cout << "foo.func1" <<endl;
       }        
    };      
} 

foo<int> f;
func1(f);   

模板参数与友元声明无关。您需要在 friend 声明中消除歧义:

template<class R>
struct foo{
   template<typename U>
   friend void func1<U>(foo<U>&){
      cout << "foo.func1" <<endl;   // cat();
   }        
};      

同样对于你的情况,你应该决定,如果你想像上面那样内联朋友定义,或者只提供一个声明:

template<class R>
struct foo{
   template<typename U>
   friend void ::func1<U>(foo<U>&);
};      

后者应显式匹配全局命名空间中的friend模板函数,必要时可特化:

template<>
void func1(int&){
   // ...
}

template<>
void func1(std::string&){
   // ...
}

// a.s.o.

您无需提供 func1 的专业化。只需提供一个重载:

namespace first {
    template <class R>
    struct foo {
        friend void func1(foo& ){
            std::cout << "foo.func1" << std::endl;
        }
    };
}

int i;
first::foo<int> f;

func(i);  // calls ::func<int>
func1(f); // calls first::func1(first::foo<int>& );

否则,您可以将专业化加为好友,但不能在 class 正文中定义专业化:

template <class R>
struct foo {
    friend void func1<>(foo& ); // friends ::func1<foo<R> >
};