Search code examples
c++function-pointers

Meaning of constant function pointer


I was reading through someone else's code that had custom function classes similar to boost::function or std::function. They were passing these function classes around by constant reference. In one section on the critical path they chose to use function pointers instead but still by constant reference with comments about greater efficiency

They had the equivalent of this in their code:

using FuncT = int(*)(int, int);

Which was being passed around like this:

const FuncT&

I assume const FuncT& isn't really any more efficient to pass than FuncT and that the syntax was just leftover of it being their custom function class originally. However it got me wondering about what the meaning of const FuncT would be

#include <iostream>

using FuncT = int(*)(int, int);

struct MyClass final {
    static int myMethod(int a_arg1, int a_arg2) {
        std::cout << a_arg1 << " " << a_arg2 << std::endl;
        return 0;
    }

    // Similar to what I found in someone's code
    void v1(const FuncT& a_func) { a_func(1, 1); }

    // A reference to a const function pointer seems meaningless, it should be
    // just as efficient to copy the pointer
    void v2(const FuncT  a_func) { a_func(2, 2); }
    //                 ^
    //                 Removed reference

    // I believe this is the syntax for a function pointer that cannot be
    // modified to point to a different function
    void v3(      int(* const a_func)(int, int)) { a_func(3, 3); }
    //                  ^
    //                  Added const not present in FuncT

    // This compiles but I don't know what the intended meaning of the extra
    // const would be
    void v4(const int(* const a_func)(int, int)) { a_func(4, 4); }
    //      ^
    //      Added const not present in v3
};

int main() {
    MyClass myClass;
    myClass.v1(&MyClass::myMethod);
    myClass.v2(&MyClass::myMethod);
    myClass.v3(&MyClass::myMethod);
    //myClass.v4(&MyClass::myMethod); // Doesn't compile
    return 0;
}

In the above code v4 compiles but what is the intended meaning of the leftmost const?


Solution

  • Minor modifications to your code:

    void v3( int(* const a_func)(int, int)) { 
        a_func = &MyClass::myMethod; // no, a_func is const
    } 
    

    a_func is const you cannot modify it. Trying to assign to it raises an error.

    Here:

    void v4(const int(* const a_func)(int, int)) { a_func(4, 4); }
    //      |-------|
            
    

    same as above, but the return type of the function is const int rather than int:

    const int foo(int,int) { return 42;}
    
    int main() {
        MyClass myClass;
        myClass.v4(&foo);
    }
    

    Live Demo

    Something that still confuses me is why const FuncT is not equivalent to v4's argument

    Grammar for function pointers is weird, thats why we use aliases as often as possible. For a thorough explanation I refer you to the respective literature. In this case it is just returntype (* outer_most_const)(parameter_types), while with the alias using f = returntype (*)(parameter_types) you add the outermost const via const f.