1

How does one define and return a function inside a function?

For instance, we have a function like:

float foo(float val) {return val * val;}

Now, what is needed is a function like bar:

typedef float (*func_t)(float)
// Rubish pseudo code
func_t bar(float coeff) {return coeff * foo();}
// Real intention, create a function that returns a variant of foo
//  that is multiplied by coeff. h(x) = coeff * foo(x)

The only thing I've came up with so far is using lambda or a class. Is there a straight forward way to do this without being convoluted needlessly?

AturSams
  • 7,568
  • 18
  • 64
  • 98
  • Do you mean `typedef float (*func_t)(float);`? (Notice the star *before* func_t, not *after*) Like: define func_t as a pointer to function that takes float and returns float? – Fabio says Reinstate Monica Nov 19 '15 at 16:52
  • @NathanOliver It says rubbish pseudo code in the comment. Pretty sure the intention is clear to anyone but a human compiler. Added another comment just in case. – AturSams Nov 19 '15 at 16:54
  • @FabioTurati Yeah, that was a mistype. – AturSams Nov 19 '15 at 16:57
  • @NathanOliver - I kinda rushed it. Thanks for the comment. :D – AturSams Nov 19 '15 at 16:58
  • 1
    There isn't a way to do it without using a lambda or a class — and I'm not sure how much of what you want to do can be done with them. Lambdas were added in part to allow machinations along the lines you're after. – Jonathan Leffler Nov 19 '15 at 16:59
  • @JonathanLeffler I meant lambda like Basile suggested. Objected it at first but the example code is very concise and noob friendly. – AturSams Nov 19 '15 at 17:30

2 Answers2

5

Use std::function

std::function<float(float)> bar(float coeff)
{
    auto f = [coeff](float x)
    {
        return coeff * foo(x);
    };

    return f;
}

You would then use it like this:

auto f = bar(coeff);
auto result = f(x);
Mohamad Elghawi
  • 2,071
  • 10
  • 14
  • What parameters does f accepts exactly? What is the return value? – AturSams Nov 19 '15 at 16:59
  • @zehelvion In this case f is a function that accepts no parameters and does not return a value. – Mohamad Elghawi Nov 19 '15 at 17:00
  • Would be great if you could elaborate on how to apply this to something in the veins of my question? – AturSams Nov 19 '15 at 17:01
  • How would you define g(f, y) that returns h where h(x) = f(x) + y; – AturSams Nov 19 '15 at 17:01
  • @MohamadElghawi You had the parameter coeff at the wrong function, I hope you don't mind my edit. By the way, you don't need to store `f` as a variable; you can return it directly. – leemes Nov 19 '15 at 17:05
  • @leemes Thanks! I guess you could pass both floats into f but that's completely up to you. And yes I know you can return it directly I guess I wanted to show a) a function being defined in another and b) returning said function. – Mohamad Elghawi Nov 19 '15 at 17:11
  • hmm, I think foo should be passed in as an argument in your example (see my edit) – AturSams Nov 19 '15 at 17:12
  • @zehelvion Well it depends. Maybe foo is a a global function somewhere or a member function of the same class. If you do want to pass it in then I would suggest sticking to std::function. – Mohamad Elghawi Nov 19 '15 at 17:14
  • @zehelvion If you want to pass foo also, you need to put it in the "capture-list" in order to use it in the lambda (to copy the value into the lambda to be available when the lambda is being called): `[coeff,foo]` – leemes Nov 19 '15 at 17:15
  • Oops, wrong link, sorry. I meant to link @zehelvion. – leemes Nov 19 '15 at 17:17
3

Closures (with std::function) -using lambda functions- in C++11 are appropriate and recommended here. So have

std::function<int(int)> translate (int delta) { 
   return [delta](int x) {return x+delta;} }

then you might later code:

 auto t3 = translate(3);

Now t3 is the "function" which adds 3, later:

 int y = t3(2), z = t3(5);

and of course have y be 5 and z be 8.

You could also use some JIT compilation library to generate machine code on the fly, e.g. GCCJIT, or LLVM or libjit, or asmjit; or you could even generate some C++ (or C) code in some generated file /tmp/mygencod.cc and fork a compilation of that (e.g. g++ -Wall -O -fPIC /tmp/mygencod.cc -shared -o /tmp/mygencod.so) into a /tmp/mygencod.so plugin then dynamically load that plugin using dlopen on POSIX systems (and later dlsym to get a function pointer from a name; beware of name mangling for C++). I am doing such things in GCC MELT

Basile Starynkevitch
  • 223,805
  • 18
  • 296
  • 547
  • If that is the only valid option, could you give a quick example doing what is intended in the question or something in the veins of that? Such as g(f, y) returns h where h(x) = f(x) + y; – AturSams Nov 19 '15 at 17:00
  • I like that it's more concise. wp – AturSams Nov 19 '15 at 17:13