函数到函数指针“衰减” [英] Function-to-function-pointer "decay"

查看:115
本文介绍了函数到函数指针“衰减”的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们知道看起来像 void()的参数将被重写为 void(*)() 。这类似于数组到指针衰减,其中 int [] 变为 int * 。在许多情况下,使用数组会将其衰减为指针。除了参数之外,函数是否衰减?

As we know a parameter that looks like void() will be rewritten as void(*)(). This is similar to array-to-pointer decay where int[] becomes int*. There are many cases where using an array will decay it to a pointer. Are there cases other than parameters where functions "decay"?

C ++标准规定:

§8.3。 5/5


...在确定每个参数的类型后,
的任何参数都会输入array of T 函数返回T分别被调整为指针
到T或指向函数返回T的指针...

... After determining the type of each parameter, any parameter of type "array of T" or "function returning T" is adjusted to be "pointer to T" or "pointer to function returning T," respectively...

因为下面的注释器似乎不相信我...这是我的编译器显示的。

Since the commenter below doesn't seem to believe me..here's what my compiler shows.

void handler(void func())
{
    func(42);
}

main.cpp: In function 'void handler(void (*)())':
main.cpp:5:12: error: too many arguments to function
     func(42);
        ^


推荐答案

考虑了左值转换:左值到右值,数组到指针和函数到指针。你可以调用这个decay,因为 std :: decay 会对这些类型做,但是标准只是调用这个函数到指针的转换[conv.func ]:

There are three conversions that are considered lvalue transformations: lvalue-to-rvalue, array-to-pointer, and function-to-pointer. You can call this "decay" since that's what std::decay will do to these types, but the standard just calls this a function-to-pointer conversion [conv.func]:


函数类型 T 的左值可以转换为类型指针指向 T 。结果是指向该函数的指针。

An lvalue of function type T can be converted to a prvalue of type "pointer to T." The result is a pointer to the function.

如果你想知道当函数到指针转换发生时的情况,它们基本上与其他两个左值转换发生时相同。如果我们按顺序执行标准,以下是函数到指针转换发生的情况的详尽列表:

If you're asking for what the cases are for when a function-to-pointer conversion happens, they are basically the same as when the other two lvalue transformations would happen. If we just go through the standard in order, the following is an exhaustive list of cases where function-to-pointer conversion happens:

使用函数作为操作数, expr] / 9:

Using a function as an operand, [expr]/9:


每当一个glvalue表达式作为一个操作数的操作数出现,要求该操作数为prvalue时,
应用$值$ b来将表达式转换为prvalue。值

Whenever a glvalue expression appears as an operand of an operator that expects a prvalue for that operand, the lvalue-to-rvalue (4.1), array-to-pointer (4.2), or function-to-pointer (4.3) standard conversions are applied to convert the expression to a prvalue.

使用函数作为varargs函数的参数,[expr.call] / 7:

Using a function as an argument to a varargs function, [expr.call]/7:


当给定参数没有参数时,传递参数的方式使得接收函数可以通过调用 va_arg 获得参数的值$ c>(18.10)...对参数表达式执行lvalue-to-rvalue(4.1),数组到指针(4.2)和函数到指针(4.3)标准转换。

When there is no parameter for a given argument, the argument is passed in such a way that the receiving function can obtain the value of the argument by invoking va_arg (18.10)... The lvalue-to-rvalue (4.1), array-to-pointer (4.2), and function-to-pointer (4.3) standard conversions are performed on the argument expression.

您可以 static_cast 移除此转换,[expr.static.cast] / 7: / p>

You can static_cast away this conversion, [expr.static.cast]/7:


任何标准转换序列的逆(第4条)不包含左值到右值(4.1),arrayto-
可以使用 static_cast显式地执行指针(4.2),函数到指针(4.3),空指针(4.10),空成员指针(4.11)或布尔(4.12)
转换

The inverse of any standard conversion sequence (Clause 4) not containing an lvalue-to-rvalue (4.1), arrayto- pointer (4.2), function-to-pointer (4.3), null pointer (4.10), null member pointer (4.11), or boolean (4.12) conversion, can be performed explicitly using static_cast.

不过,你传入的操作数会被转换,[expr.static.cast] / 8:

Though otherwise, the operand you pass in will get converted, [expr.static.cast]/8:


数值到值(4.1),数组到指针(4.2)和函数到指针(4.3)转换应用于
操作数。

The lvalue-to-rvalue (4.1), array-to-pointer (4.2), and function-to-pointer (4.3) conversions are applied to the operand.

使用 reinterpret_cast ,[expr.reinterpret.cast] / 1:

Using reinterpret_cast, [expr.reinterpret.cast]/1:


表达式 reinterpret_cast< T& (v)是将表达式 v 转换为类型
T 。如果 T 是一个左值引用类型或对函数类型的右值引用,结果是一个左值;如果 T 是对对象类型的
值引用,结果是xvalue;否则,结果是prvalue,并且
表达式执行标准转换
(4.1),数组到指针(4.2)和函数到指针(4.3) code> v 。

The result of the expression reinterpret_cast<T>(v) is the result of converting the expression v to type T. If T is an lvalue reference type or an rvalue reference to function type, the result is an lvalue; if T is an rvalue reference to object type, the result is an xvalue; otherwise, the result is a prvalue and the lvalue-torvalue (4.1), array-to-pointer (4.2), and function-to-pointer (4.3) standard conversions are performed on the expression v.

使用 const_cast ,[expr.const.cast],与上述基本相同的措辞。使用条件运算符[expr.cond]:

Using const_cast, [expr.const.cast], with basically identical wording to the above. Using the conditional operator, [expr.cond]:


Lvalue-to-rvalue(4.1),数组到指针,并在第二个和第三个操作数上执行函数到指针(4.3)标准转换

Lvalue-to-rvalue (4.1), array-to-pointer (4.2), and function-to-pointer (4.3) standard conversions are performed on the second and third operands.

所有上述情况下,它总是所有的左值转换。

Notice in all of the above cases, it's always all of the lvalue transformations.

在模板中也会发生函数到指针的转换。将函数作为非类型参数传递[temp.arg.nontype] /5.4:

Function-to-pointer conversions also occur when in templates. Passing a function as a non-type parameter, [temp.arg.nontype]/5.4:


对于非类型参数<应用函数到指针转换(4.3)

For a non-type template-parameter of type pointer to function, the function-to-pointer conversion (4.3) is applied



p>或类型扣除,[temp.deduct.call] / 2:

Or type deduction, [temp.deduct.call]/2:


如果 P 不是引用类型:


  • - 如果 A 类型,由数组到指针标准转换(4.2)产生的指针类型是
    ,用于代替 A 用于类型扣除;否则

  • - 如果 A 是函数类型,则由函数指针标准转换生成的指针类型
    代替 A 用于类型扣除;否则,

  • — If A is an array type, the pointer type produced by the array-to-pointer standard conversion (4.2) is used in place of A for type deduction; otherwise,
  • — If A is a function type, the pointer type produced by the function-to-pointer standard conversion (4.3) is used in place of A for type deduction; otherwise,

或转换函数模板扣除,

Or conversion function template deduction, with roughly the same wording.

最后,当然,在[meta.trans.other]中定义的 std :: decay 强调我:

And lastly, of course, std::decay itself, defined in [meta.trans.other], emphasis mine:


U remove_reference_t< T> ; 。如果 is_array< U> :: value 为真,则
成员typedef类型应等于 remove_extent_t< U> * 如果 is_function< U> :: value 为真,则成员typedef类型应等于
add_pointer_t< U> c $ c>
。否则,成员typedef类型等于
remove_cv_t< U> 。 [注意:这种行为类似于当一个左值表达式用作一个值时,应用的
lvalue-to-rvalue(4.1),数组到指针(4.2)和函数到指针rvalue,但也从类类型剥离 cv - 限定符,以便更紧密地建模
参数传递。 -end note]

Let U be remove_reference_t<T>. If is_array<U>::value is true, the member typedef type shall equal remove_extent_t<U>*. If is_function<U>::value is true, the member typedef type shall equal add_pointer_t<U>. Otherwise the member typedef type equals remove_cv_t<U>. [ Note: This behavior is similar to the lvalue-to-rvalue (4.1), array-to-pointer (4.2), and function-to-pointer (4.3) conversions applied when an lvalue expression is used as an rvalue, but also strips cv-qualifiers from class types in order to more closely model by-value argument passing. —end note ]

这篇关于函数到函数指针“衰减”的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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