NPS
NPS

Reputation: 6355

Difference of type between "fun" and "&fun"?

Do expressions fun and &fun have the same type or not?

Consider the following code:

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;

Both assertions succeed which suggests that both expressions have the same type. However, typeids return different results:

FvvE
PFvvE

Why is that?

Upvotes: 32

Views: 3532

Answers (3)

user7860670
user7860670

Reputation: 37588

Both assertions succeed because they are applied to the type T deduced from function argument. In both cases it will be deduced as a pointer to function because functions decay to a pointer to function. However if you rewrite assertions to accept types directly then first one will fail:

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

online compiler

Upvotes: 30

songyuanyao
songyuanyao

Reputation: 173004

fun and &fun refer to the same type because of function to pointer conversion, which is performed in check<void(*)()>(fun);; but typeid is an exception.

(emphasis mine)

Lvalue-to-rvalue, array-to-pointer, or function-to-pointer conversions are not performed.

And why the function to pointer conversion is performed for check<void(*)()>(fun);, because in template argument deduction,

Before deduction begins, the following adjustments to P and A are made:

1) If P is not a reference type,

  • if A is an array type, ...;
  • otherwise, if A is a function type, A is replaced by the pointer type obtained from function-to-pointer conversion;

check() takes parameter by value, then function-to-pointer conversion is performed and the deduced type of T will be the function pointer too, i.e. void(*)().

Upvotes: 18

Some programmer dude
Some programmer dude

Reputation: 409422

When you use a function name as an expression, it decays to a pointer to itself. So fun will be the same as &fun.

As for the typeid thing, from this reference:

Lvalue-to-rvalue, array-to-pointer, or function-to-pointer conversions are not performed.

[Emphasis mine]

Upvotes: 7

Related Questions