微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

c – 为什么无法将函数指针与模板函数进行比较?

请考虑以下代码
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
}

如果您取消对test2行的注释,并尝试使用g编译代码,则会收到以下错误

test.cpp: In function ‘int main()’:
test.cpp:8:21: error: assuming cast to type ‘void (*)(int)’ from overloaded function [-fpermissive]
     bool test2 = p==templatedFunc<int>; // compilation error
                     ^~~~~~~~~~~~~~~~~~

我得到这个结果在g 5.3.0和6.2.0.同时,编译与cl 3.6.0成功,没有警告.

哪个编译器根据标准这里是正确的,这给出错误或cl,哪些不?

如果g是正确的,那么为什么在需要显式地址的运算符的时候,为什么有正常的函数与模板函数的不对称性呢?

解决方法

这是一个gcc错误,你在一个角落的情况下,在C标准中,重载功能的地址§13.4([over.over] / 1)):

A use of an overloaded function name without arguments is resolved in certain contexts to a function,a
pointer to function or a pointer to member function for a specific function from the overload set. A function
template name is considered to name a set of overloaded functions in such contexts. The function selected
is the one whose type is identical to the function type of the target type required in the context. [ Note:
That is,the class of which the function is a member is ignored when matching a pointer-to-member-function
type. — end note ] The target can be:

(1.1) — an object or reference being initialized (8.5,8.5.3,8.5.4),

(1.2) — the left side of an assignment (5.18),

(1.3) — a parameter of a function (5.2.2),

(1.4) — a parameter of a user-defined operator (13.5),

(1.5) — the return value of a function,operator function,or conversion (6.6.3),

(1.6) — an explicit type conversion (5.2.3,5.2.9,5.4),or

(1.7) — a non-type template-parameter (14.3.2).

The overloaded function name can be preceded by the & operator. An overloaded function name shall not
be used without arguments in contexts other than those listed. [ Note: Any redundant set of parentheses
surrounding the overloaded function name is ignored (5.1). — end note ]

你看到从(1.1)到(1.7)的列表中缺少什么…内置的运算符!

如果你声明一个operator ==的重载,那么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

}

test2和test3使用gcc进行编译. test4没有在gcc上编译,但是没有重载解析,你明确专门的功能.真的应该编译test5不按照标准进行编译.在这种情况下,gcc会产生与test4完全相同的错误信息.这肯定是一个gcc错误.

原文地址:https://www.jb51.cc/c/115661.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐