same as having a pointer to int pointing to a double. A const member function is not a const-qualified function (those don't exist, anyway), it's a different type entirely.
Why are they disparate types? In all other places in C++, a non-const may be implicitly converted to a const - why is it inconsistent here? (I'm not talking about the pointer variable itself, which would indeed be implicitly convertible to const.)
What I mean is, what technical reasons are there for not allowing this conversion? Would I be able to safely do it manually?
"All other places is really just two, to quote cppreference,
A prvalue of type pointer to cv-qualified type T can be converted to prvalue pointer to a more cv-qualified same type T (in other words, constness can be added)
A prvalue of type pointer to member of cv-qualified type T in class X can be converted to prvalue pointer to member of more cv-qualified type T in class X.
This case isn't one of those two: there are no cv-qualified function types.
The type system is too strict to allow calling functions with different calling signatures (in this case, void(const Test&) and void(Test&)) through the same pointer. Can't you convert both into function objects?
#include <iostream>
#include <functional>
struct Test
{
void f() { std::cout << "f" << std::endl; }
void g() const { std::cout << "g" << std::endl; }
};
int main() {
std::function<void(Test&)> f = &Test::f;
std::function<void(const Test&)> g = &Test::g;
// C++ provides no conversion from const to non-const.
// const int a;
// int& b = a; // basically what you are trying to do.
Test t;
f(t);
g(t);
return 0;
}
The problem is that my template functions act explicitly on member function pointers, and I don't know a way to allow the compiler to autogenerate my code for both const and non-const versions of member function pointers.
Yeah, because I actually have to perform some checking and transformations on each argument type of the member function (auto-converting between std::string and char const *, for example). I guess for now I will just have to not support const member functions until I find a way.
Lines 18 and 21 are templates and simply to cast a pointer to a function into a std::function type so you don't have to set the DoCall template parameters.
Any work you do with the template arguments is going to happen in DoCall.