如果没有显式&的原因,为什么不能将函数指针与模板函数进行比较?在函数名称上? [英] Why can't one compare a function pointer to a template function without explicit & on function name?

查看:62
本文介绍了如果没有显式&的原因,为什么不能将函数指针与模板函数进行比较?在函数名称上?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

考虑以下代码:

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 ++编译代码,则会出现以下错误:

If you uncomment the test2 line and try to compile the code with g++, you'll get the following error:

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上得到了这个结果.同时,使用clang ++ 3.6.0进行编译会成功,而不会发出警告.

I get this result on g++ 5.3.0 and 6.2.0. At the same time, compilation with clang++ 3.6.0 succeeds without warnings.

根据此处的标准,哪个编译器是正确的-g ++会给出错误,而clang ++却不会?

Which compiler is correct according to the Standard here — g++, which gives an error or clang++, which doesn't?

如果g ++是正确的,那么为什么在需要显式地址运算符的情况下,普通函数与模板函数之间存在这样的不对称性?

And if g++ is right, then why is there such an asymmetry with normal functions vs templated functions regarding the need of explicit address-of operator?

推荐答案

这是gcc错误,在C ++标准中,重载函数的地址§13.4( [over.over]/1):

This is a gcc bug, and you are in a corner case, in the C++ standard, Address of overloaded function §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)-正在初始化的对象或引用(8.5、8.5.3、8.5.4),

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

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

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

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

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

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

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

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

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

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

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

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

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

重载的函数名称可以以&开头.操作员.重载的函数名称不应 在列出的上下文之外的上下文中不带参数的情况下使用. [注意:任何多余的括号 重载函数名周围的内容将被忽略(5.1). —尾注]

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)中缺少什么吗?内置运算符!

Do you see what is lacking in the list from (1.1) to (1.7)... built-in operators!

如果您声明operator ==的重载,则两个gcc都不会抱怨比较,而不必显式地专门化模板函数:

If you declare an overload of operator == both gcc will not complain with the comparison, more than that you do not have to explicitly specialize the template function:

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

}

test2test3用gcc编译. test4不能在gcc上编译,但是没有重载解析,因此您明确地对该函数进行了专门化.它确实应该编译. test5不能按照标准中的说明进行编译.在这种情况下,gcc会产生与test4完全相同的错误消息.这肯定是gcc错误.

test2 and test3 compiles with gcc. test4 does not compile on gcc, but there are no overload resolution, you explicitly specialized the function. It really should compile. test5 does not compile as stated in the standard. In this case gcc produces the exact same error message as for test4. This is surely a gcc bug.

这篇关于如果没有显式&amp;的原因,为什么不能将函数指针与模板函数进行比较?在函数名称上?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆