C++ 为什么可以';t在没有显式&;的情况下,将函数指针与模板函数进行比较;关于函数名?

C++ 为什么可以';t在没有显式&;的情况下,将函数指针与模板函数进行比较;关于函数名?,c++,templates,function-pointers,C++,Templates,Function Pointers,考虑以下代码: void func(int) {} template<typename T> void templatedFunc(T) {} int main() { void (*p)(int) = func; bool test1 = p==func; //bool test2 = p==templatedFunc<int>; // compilation error bool test3 = p==&templatedFu

考虑以下代码:

void func(int) {}
template<typename T> void templatedFunc(T) {}
int main()
{
    void (*p)(int) = func;

    bool test1 = p==func;
    //bool test2 = p==templatedFunc<int>; // compilation error
    bool test3 = p==&templatedFunc<int>; // but this works
}
我在g++5.3.0和6.2.0上得到了这个结果。同时,使用clang++3.6.0编译成功,没有任何警告

根据这里的标准-g++,哪个编译器是正确的,它给出了一个错误,哪个编译器不是


如果G+是正确的,那么为什么对于函数的显式地址的需要,有正常函数与模板函数的不对称性?

< P>这是一个GCC bug,而你在一个角的情况下,在C++标准中,重载函数13.4的地址([On.Over)/ 1):

不带参数的重载函数名的使用在某些上下文中解析为函数,即 重载集中特定函数的函数指针或成员函数指针。函数 模板名称被认为是在这样的上下文中命名一组重载函数。选择的功能 类型与上下文中所需的目标类型的函数类型相同的函数类型。[注: 也就是说,当匹配指向成员函数的指针时,将忽略该函数所属的类 类型。-结束注释]目标可以是:

(1.1)-正在初始化的对象或参考(8.5、8.5.3、8.5.4)

(1.2)-作业的左侧(5.18)

(1.3)-函数的参数(5.2.2)

(1.4)-用户定义运算符(13.5)的参数

(1.5)-函数、运算符函数或转换的返回值(6.6.3)

(1.6)-显式类型转换(5.2.3、5.2.9、5.4),或

(1.7)-非类型模板参数(14.3.2)

重载函数名前面可以加上&运算符。重载函数名不应 在除列出的上下文以外的上下文中不带参数使用。[注:任何多余的括号集 忽略重载函数名周围的内容(5.1)。-结束注释]

你看到从(1.1)到(1.7)的列表中缺少什么了吗。。。内置操作员

如果声明重载
运算符==
两个gcc都不会抱怨比较,更重要的是,您不必显式专门化模板函数:

void func(int) {}
template<class T>
void templatedFunc(T) {}
struct s{};
bool operator==(s, void(*)(int)){return false;}
int main()
{
   void (*p)(int) = templatedFunc;

   bool test1 = p==func;
   bool test2 = s{} == templatedFunc<int>; // no error - no overload resolution
   bool test3 = s{} == templatedFunc; // no error - overload resolution
   bool test4 = p == templatedFunc<int>; // gcc error, but not an error -
                                         // no overload resolution
 //bool test5 = p == templatedFunc; // error - overload resolution not
                                 // performed for built-int operators

}
void func(int){}
模板
void templatedFunc(T){}
结构s{};
布尔运算符==(s,void(*)(int)){return false;}
int main()
{
void(*p)(int)=模板函数;
bool test1=p==func;
bool test2=s{}==templatedFunc;//无错误-无重载解析
bool test3=s{}==templatedFunc;//无错误-重载解析
bool test4=p==templatedFunc;//gcc错误,但不是错误-
//无过载分辨率
//bool test5=p==templatedFunc;//错误-重载解析不正确
//为内置int运算符执行
}

test2
test3
与gcc一起编译
test4
不在gcc上编译,但是没有重载解决方案,您显式地专门化了该函数。它真的应该编译<代码>测试5未按照标准中的规定编译。在这种情况下,gcc产生与
test4
完全相同的错误消息。这肯定是一个gcc错误。

我的常识告诉我clang在这种情况下是正确的,因为完全专用的函数模板(或者更确切地说是一个实例化)被认为是一个正常的函数,因此应该这样做。它允许您执行
void(*p)(int)=templatedFunc
,还是这也需要
&
呢?顺便说一句,惯用的方法是使用
&
@TripeHound奇怪的是,g++在这种情况下没有抱怨。
void func(int) {}
template<class T>
void templatedFunc(T) {}
struct s{};
bool operator==(s, void(*)(int)){return false;}
int main()
{
   void (*p)(int) = templatedFunc;

   bool test1 = p==func;
   bool test2 = s{} == templatedFunc<int>; // no error - no overload resolution
   bool test3 = s{} == templatedFunc; // no error - overload resolution
   bool test4 = p == templatedFunc<int>; // gcc error, but not an error -
                                         // no overload resolution
 //bool test5 = p == templatedFunc; // error - overload resolution not
                                 // performed for built-int operators

}