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
?
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);
}
Something that still confuses me is why
const FuncT
is not equivalent tov4
'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
.