3

I want to create a function that returns a function that checks whether a given int is within certain bounds. Therefore the returned function should only take one parameter, an int, and return a bool. This is necessary as the returned function is passed on as a function pointer to another function. So far I would only be able to do it like this:

bool valueIsInBounds(int value) { return value >= 0 && value <= 100; }

int main() {
    functionThatTakesAFunction(&valueIsInBounds);
}

0 and 100 are obviously fixed values, and I would like to change that.
What I would like to be able to do is something like this:

??? functionGenerator(int min, int max) { ??? }

int main() {
    functionThatTakesAFunction(&(functionGenerator(0, 100)));
}

I know this is doable in other languages, though I don't know how this would be achieved in C.

Marcus Rossel
  • 3,196
  • 1
  • 26
  • 41
  • It isn't doable in C. Functions can't be dynamically created at runtime. – John Coleman Dec 19 '16 at 12:55
  • Barring some elaborate machinery to implement first-class functors before writing this on top of it, you can't do that in C. – Quentin Dec 19 '16 at 12:55
  • The general description can be found here: http://stackoverflow.com/questions/840501/how-do-function-pointers-in-c-work – coffeemakr Dec 19 '16 at 12:56
  • 2
    shameless plug for [C++ lambdas](http://en.cppreference.com/w/cpp/language/lambda) – Vittorio Romeo Dec 19 '16 at 12:57
  • you can't do this without altering the type of the returned function. – bolov Dec 19 '16 at 12:58
  • 2
    @VittorioRomeo how is a C++ functionality at all relevant to a C question ? – Quentin Dec 19 '16 at 12:58
  • Side note: `&` in `functionThatTakesAFunction(&valueIsInBounds)` is useless. – LPs Dec 19 '16 at 13:02
  • You should post the `functionThatTakesAFunction` prototype. And you should state if you can change its declaration. – LPs Dec 19 '16 at 13:02
  • @Quentin: on the slim chance "other languages" does not include "C++", it might be interesting for the OP to know that there's a language which is mostly backwards-compatible with C which has the desired feature. Maybe his use case allows him to use C++ instead of C - this is why it's just a comment and not an answer. It **may** be of interest to the OP. – Vittorio Romeo Dec 19 '16 at 13:03
  • 1
    @Quentin As a *comment* it is definitely relevant. If OP has a very strong reason for wanting to do this and already has a code base in C, converting it to C++ to take advantage of such things would be one possible strategy. – John Coleman Dec 19 '16 at 13:05
  • Maybe your function needs to return a function pointer – Dimitri Dec 19 '16 at 13:07
  • A naïve potential solution is to have the bounds to the comparison function be public variables with your intended function to return a function downgraded to a simple function that assigns to public variables. This will only work if you only need one comparison function at a time. If you need at most a small fixed number at a time, you could have e.g. 3 or 4 of these functions defined with the intended function assigning to the right public variables and returning a pointer to the right function. – John Coleman Dec 19 '16 at 13:15

2 Answers2

4

Sorry. As the comments says, this can not be implemented in portable C.

You must generate some assembly yourself to bind the parameters (max & min) to the function pointer. This is called a «trampoline» function, and there exists multiple libraries for that. Here is one: https://www.gnu.org/software/libffcall/trampoline.html

Take a look at this SO post for an better explanation and an example of using the trampoline library above.

Community
  • 1
  • 1
4

As dynamically generating a function cannot be done in C, the next best approach will be to parametrize the function.

You can pass (as in your question) the bounds as additional parameters, or you can set global or static variables with these bounds.

bool valueIsInBounds(int value, int min, int max) { return value >= min && value <= max; }

int main() {
    functionThatTakesAFunction(valueIsInBounds);
}

or:

int gMin, gMax;
void setBounds(int min, int max) { gMin= min; gMax= max; }
bool valueIsInBounds(int value)  { return value >= gMin && value <= gMax; }

int main() {
    setBounds(0, 100);
    functionThatTakesAFunction(valueIsInBounds);
}
Paul Ogilvie
  • 25,048
  • 4
  • 23
  • 41