Search code examples
c++constantsconstexprautopointer-to-member

What auto keyword does under the hood when used with function pointers?


While experimenting with auto and function pointers I notice a strange behavior

class Test
{
public:
    void Func(){}
};

static constexpr const auto member_ptr1{ &Test::Func }; // compile fine
static constexpr const void(Test::*member_ptr2)(void) { &Test::Func }; // ERROR : cannot convert from void(Test::*)(void) to const void(Test::* const)(void)

I understand that, in the case of member_ptr2, the compiler complain about not finding a function with the signature const void Func() , but it should trigger the same error for member_ptr1.

So what does the compiler do under the hood with member_ptr2 ?

Bonus question : what does const means right after Test::* ? I notice that in the compiler output.

Second bonus question : When using function pointers is there any difference between constexpr const auto member_ptr1{...} and constexpr auto member_ptr1{...} ?


Solution

  • This

    static constexpr const auto member_ptr1{ &Test::Func }; 
    

    declares a constant pointer to a member function. That is the pointer itself that is constant.

    This record is equivalent to

    static constexpr void(Test::* const member_ptr2)(void) { &Test::Func };
    

    Here is a demonstrative program.

    #include <iostream>
    #include <iomanip>
    #include <type_traits>
    
    class Test
    {
    public:
        void Func(){}
    };
    
    static constexpr const auto member_ptr1{ &Test::Func }; // compile fine
    static constexpr void(Test::* const member_ptr2)(void) { &Test::Func };
    
    int main() 
    {
        std::cout << std::boolalpha 
                  << std::is_same<decltype( member_ptr1 ), decltype( member_ptr2 )>::value
                  << '\n';
                  
        return 0;
    }
    

    Its output is

    true
    

    And here is another simplified demonstrative program.

    #include <iostream>
    
    int main() 
    {
        int x = 10;
        const auto p = &x;
        
        *p = 20;
        
        std::cout << "x = " << x << '\n';
        
        return 0;
    }
    

    The program output is

    x = 20
    

    That is the pointer p has the type int * const not the type const int *.

    The type in place of the placeholder auto at first is deduced from the used initializer and then the qualifier const is applied to the deduced type.