Search code examples
c++c++11function-pointersimplicit-conversiondecltype

Differences between `decltype(&ordenary_func)` and decltype`(ordenary_func)`


Given the declaration void close_file_func(std::FILE* fd){}, I found that decltype(&close_file_func) is the type of void (*)(_IO_FILE*) whereas decltype(close_file_func) is the type of void (_IO_FILE*)?

You could check the related code trough https://godbolt.org/z/QK5q3o.

For your convenience, i post the code and the execution output below.

#include<iostream>
#include<typeinfo>

void close_file_func(std::FILE* fd);

int main()
{
    std::cout << typeid(close_file_func).name() << std::endl;
    std::cout << typeid(&close_file_func).name() << std::endl;
}

//Terminate outputs:
//FvP8_IO_FILEE
//PFvP8_IO_FILEE

And echo 'PFvP8_IO_FILEE' | c++filt -t says void (*)(_IO_FILE*) ,

echo "FvP8_IO_FILEE" | c++filt -t says void (_IO_FILE*).

And this expression(std::cout << (close_file_func == &close_file_func) << std::endl;) is legal.You see, close_file_func == &close_file_func returns true.

I thought over and over, but i still could not understand. I would be grateful for any hint on this question.


Solution

  • You might think that both should give the same type as function pointer. Yes, function-to-pointer implicit conversion might be performed in some contexts1, but not for decltype(close_file_func) (and typeid(close_file_func)).

    When used with entity, decltype would yield the type of the entity; so decltype(close_file_func) yield the function type exactly, i.e. void (_IO_FILE*).

    1) If the argument is an unparenthesized id-expression or an unparenthesized class member access expression, then decltype yields the type of the entity named by this expression.

    On the other hand &close_file_func takes the address of the function and returns function pointer, then decltype(&close_file_func) yields the function pointer type, i.e. void (*)(_IO_FILE*).


    1 For operator==,

    (emphasis mine)

    In all cases, for the built-in operators, lhs and rhs must have either

    • arithmetic or enumeration type (see arithmetic comparison operators below)
    • pointer type (see pointer comparison operators below)

    after the application of the lvalue-to-rvalue, array-to-pointer and function-to-pointer standard conversions.

    Function-to-pointer implicit conversion is performed on the left operand so close_file_func == &close_file_func is comparing the function pointers.