表达式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
为什么?
答案 0 :(得分:29)
两个断言都成功,因为它们应用于从函数参数推导出的类型T
。在这两种情况下,它都将被推断为函数的指针,因为函数会衰减为指向函数的指针。但是,如果您重写断言以直接接受类型,那么第一个将失败:
static_assert(is_same<void(*)(), decltype(fun)>::value);
static_assert(is_same<void(*)(), decltype(&fun)>::value);
答案 1 :(得分:17)
fun
和&fun
引用相同的类型,因为function to pointer conversion是在check<void(*)()>(fun);
中执行的;但是typeid
是一个例外。
(强调我的)
Lvalue-to-rvalue,array-to-pointer或函数到指针的转换未执行。
为什么要对check<void(*)()>(fun);
执行指针转换功能,因为在template argument deduction中,
在扣除开始之前,会对 P 和 A 进行以下调整:
1)如果 P 不是参考类型,
- 如果 A 是数组类型,...;
- 否则,如果 A 是函数类型, A 将替换为从函数到指针转换获得的指针类型;
check()
按值获取参数,然后执行函数到指针的转换,推导出的T
类型也将是函数指针,即void(*)()
。
答案 2 :(得分:6)
当您使用函数名作为表达式时,它衰减指向自身的指针。因此fun
与&fun
相同。
关于typeid
事,来自this reference:
不执行Lvalue-to-rvalue,数组到指针或函数到指针转换。
[强调我的]