Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Restricting conversion of function pointers

I wonder why a static_cast from int (*)(const int&) to type int (*)(int&) is illegal. If I have a function pointer that technically allows accepting an int& but want to assign to it a function which voluntarily waives the permission to modify the pointed-to value, shouldn't it behave just as a special case of a function that in principle could?

In other words, given that I can pass an arbitrary int& to an int (*)(const int&) function, is there a deeper reason in the standard why the latter can't be considered a special case of int (*)(int&) and assigned to such variable?

M(!W)E:

int g(const int& q) {
  return q;
}

int main() {
  int (*f)(int&) = static_cast<int(*)(int&)>(g); // breaks
  int x = 1;
  return f(x);
}
like image 991
The Vee Avatar asked Oct 30 '17 16:10

The Vee


1 Answers

[...] is there a deeper reason in the standard why [...]

These questions are typically impossible to answer. Maybe nobody thought of it as a worthwhile thing to look into. C++ in general has limited support for covariance and contravariance. There are plenty of other safe conversions that are potentially possible, not just qualifying the references.

For instance, a function pointer like Animal*(*)(Dog*) could be initializeable from both Animal*(*)(Animal*) and Dog*(*)(Dog*). But today, neither conversion is supported.

So the real answer is probably: write a proposal.


However, in this case, we can still accomplish the desired behavior through a clearly underappreciated rule: Almost Always Lambda. We know, by name, the function we want to use, and lambdas without capture (which we don't need) can be converted into function pointers:

int (*f)(int&) = [](int& i) { return g(i); };
like image 179
Barry Avatar answered Sep 18 '22 01:09

Barry