"fun"和"&fun"之间的类型区别是什么?

32

表达式 fun&fun 的类型是否相同?

考虑以下代码:

template <typename Check, typename T>
void check(T)
{
    static_assert(is_same<Check, T>::value);
}

void fun()
{}

check<void(*)()>(fun);
check<void(*)()>(&fun);

cout << typeid(fun).name() << endl;
cout << typeid(&fun).name() << endl;

两个断言都成功了,这表明两个表达式具有相同的类型。然而,typeid返回不同的结果:

FvvE
PFvvE

为什么会这样?
3个回答

30

两个断言都成功了,因为它们应用于从函数参数推导出的类型T。在这两种情况下,它将被推导为指向函数的指针,因为函数会衰变为指向函数的指针。然而,如果您将断言重写为直接接受类型,则第一个断言将失败:

static_assert(is_same<void(*)(), decltype(fun)>::value);
static_assert(is_same<void(*)(), decltype(&fun)>::value);

在线编译器

该链接指向一个在线编译器。

18
fun&fun指的是同一类型,这是由于在check<void(*)()>(fun);中执行了函数指针转换。但typeid是个例外。

(强调是我的)

Lvalue-to-rvalue、数组到指针或函数到指针转换不会被执行

为什么对于check<void(*)()>(fun);会执行函数到指针转换呢?因为在模板参数推导中,

在推导开始之前,对PA进行以下调整:

1)如果P不是引用类型,则

  • 如果A是数组类型,...;
  • 否则,如果A是函数类型,则将A替换为从函数到指针转换获得的指针类型;

check()通过值传递参数,然后执行函数到指针转换,所以推导出的T类型也将是函数指针类型,即void(*)()


7
当您将函数名用作表达式时,它会自动转化为指向函数本身的指针。因此,`fun` 将与 `&fun` 相同。
至于 `typeid`,来自于这个参考链接
引用如下: "Lvalue-to-rvalue、数组到指针或者函数到指针的转换不会被执行。
[强调为我所加]"

为什么 typeid 返回不同的类型名称? - NPS
@NPS 因为“函数到指针的转换不会被执行”。 - Zereges
[conv.func]/1说它可以(“函数类型T的左值可以转换为类型为'指向T的指针'的纯右值。结果是一个指向该函数的指针。”),但我找不到规则说明它会这样做。 - YSC
@YSC 在模板参数推导中确实如此;check按值接受参数,而推导出的类型T将是函数指针。 - songyuanyao
“使用作为表达式”是什么意思?在什么情况下使用?在什么情况下不使用? - NPS

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接