C++ 使用模板友元函数时未解析的重载函数类型

C++ 使用模板友元函数时未解析的重载函数类型,c++,boost,boost-function,C++,Boost,Boost Function,我遇到一个问题,我试图将类模板的友元函数塞进boost::function: #include <boost/function.hpp> template <int N> struct Vec{ friend double dot(Vec, Vec){} }; template class Vec<2>; //Force multiple instantiations template class Vec<3>; int main

我遇到一个问题,我试图将类模板的友元函数塞进
boost::function

#include <boost/function.hpp>

template <int N>
struct Vec{
   friend
   double dot(Vec, Vec){}
};

template class Vec<2>; //Force multiple instantiations
template class Vec<3>;

int main()
{
    boost::function<double  (Vec<2>, Vec<2>)> func = dot;
    double (*func1)(Vec<2>, Vec<2>) = dot;
}
第二行的错误对我来说更令人困惑:

error: no matches converting function 'dot' to type 'double (*)(struct Vec<2>, struct Vec<2>)'
testtmpl.C:6:15: error: candidates are: double dot(Vec<2>, Vec<2>)
testtmpl.C:6:15: error:                 double dot(Vec<3>, Vec<3>)
错误:将函数“dot”转换为类型“double(*)(结构向量,结构向量)”时没有匹配项
testtmpl.C:6:15:错误:候选项是:双点(Vec,Vec)
testtmpl.C:6:15:错误:双点(Vec,Vec)
我有点困惑,因为我不明白为什么
双点(Vec,Vec)
不匹配

关于这里发生的事情有什么想法吗?

这将起作用:

template <int N> struct Vec;

template <int K> double dot(Vec<K>, Vec<K>) { return 0; }

template <int N>
struct Vec
{
  friend double dot<>(Vec<N>, Vec<N>);
};
模板结构向量;
模板双点(Vec,Vec){返回0;}
模板
结构向量
{
朋友双点(Vec,Vec);
};
GCC 4.6.1实际上给出了一个非常有用的警告:

警告:友元声明“双点(Vec,Vec)”声明非模板函数[-Wnon-template-friend]
注意:(如果这不是您想要的,请确保函数模板已经声明并添加到函数名称之后)

在我的理解中,如果友元函数是在没有其他函数的类中定义的 相应的声明,只能通过ADL查找朋友名。
§7.3.1.2/3规定:

通过简单的名称查找,直到 在该命名空间范围中提供了匹配声明

代码可以通过添加相应的 函数声明
双点(Vec,Vec)
喜欢

.

这段代码的语义与原始代码略有不同。如果存在从任何内容到
Vec
的隐式转换,则不会应用这些转换,因为模板的重载解析需要参数的完美匹配。。。它为模板的每个实例化定义一个友元函数,该函数是内联定义的。。。这是一段相当常见的代码。认为friend函数可能被称为
操作符+1,这是有意义的。昨晚我在想这个,出于某种原因我放弃了,但这确实有道理。由于原始代码已经在执行显式实例化,因此必须声明所有函数应该不是问题。另一种选择是创建一个模板化的自由成员函数,它将执行调度(<代码> DOT/C++ >将通过ADL内部访问)。当我第一次听到这个解释时,我撕了我的头:)任何流行的C++作者/ Guru曾经推荐在它成为朋友之前总是声明一个函数?(我似乎还记得一些关于函数模板朋友的事情。)这是我的经验法则,但我不知道它是否解决了很多问题。链接不再起作用。
template <int N> struct Vec;

template <int K> double dot(Vec<K>, Vec<K>) { return 0; }

template <int N>
struct Vec
{
  friend double dot<>(Vec<N>, Vec<N>);
};