10

I want to create a general function which returns a function pointer to another function in C/C++. However, second returned function should be able to use variable from first function.

Example,

typedef double (*func_t)(double);

func_t inverse(func_t fn) {
   // define another function here that uses fn
   double solve(double x) {
      // use fn
   }
   return &solve;
}

double sqr(double x) { return x * x; }

int main() {
     func_t inv = inverse(sqr);
     printf("sqrt %d = %f\n", 100, inv(100)); 
}

Obviously gcc, g++ do not allow me to do this. Can I achieve this without using classes or structs.

Guilherme Bernal
  • 8,183
  • 25
  • 43
morazow
  • 251
  • 1
  • 8

8 Answers8

5

This is not about nested functions; this is about closures. GCC's nested functions are a half-implemented form of closure that does not do what the question is asking for.

C, going by any of the standards, does not support closures at all.

C++11 supports closures through lambdas, and there are a few other solutions specific to C++ as well.

Apple's Clang compiler does support closures as an extension in C mode, in the form of "blocks". Unlike nested functions, these actually work for the requested use case (i.e. being returned to a higher call level).

You'd write it out something like this:

typedef double (^func_t)(double);  // block type is slightly different from function pointer

func_t inverse(func_t fn) {
   return ^ double(double x) {
       //use fn
   };
}

// ...etc., same from here

But if you want to make extensive use of closures, you really need to use a different language. You'll run into serious complications in C because of the lack of any kind of memory management (unrestricted closures are a nightmare to manage by hand).

Alex Celeste
  • 12,824
  • 10
  • 46
  • 89
4

Answering for C:

C does not support nested functions (defining a function inside another function) but gcc allows it as a GNU extension to C.

http://gcc.gnu.org/onlinedocs/gcc/Nested-Functions.html

ouah
  • 142,963
  • 15
  • 272
  • 331
  • 3
    Most relevant thing behind this link is: "If you try to call the nested function through its address after the containing function exits, all hell breaks loose." – zch Oct 22 '13 at 19:32
  • It would be nice to mention `-pedantic` and `-pedantic-errors` which is covered [here](http://gcc.gnu.org/onlinedocs/gcc/C-Extensions.html#C-Extensions). – Shafik Yaghmour Oct 22 '13 at 19:34
  • Question is rather about closures than nested functions per se. GNU C allows defining nested functions byt not returning them, which is what OP asked for. – el.pescado - нет войне Oct 30 '13 at 07:56
4

This is possible in C++11 with a lambda:

#include <cstdio>
#include <cmath>
#include <functional>

typedef std::function<double(double)> func_t;

func_t inverse(func_t fn) {
    return [=](double x) { printf("fn(x): %f\n", fn(x)); return sqrt(x); };
}

double sqr(double x) { return x * x; }

int main() {
    auto inv = inverse(sqr);
    printf("sqrt %d = %f\n", 100, inv(100));
}
mattnewport
  • 13,728
  • 2
  • 35
  • 39
2

If you can use C++11, them lambda functions are your friend:

#include <functional>
#include <iostream>

std::function<double(double)> identity(std::function<double(double)> fn)
{
  return [fn](double x){
    // Do your logic here
    return fn(x);
  };
}

double sqr(double x) { return x * x; }

int main() {
  auto f = identity(sqr);
  std::cout << "sqr(100) = " << f(100) << std::endl;
}

If you don't plan to support C++11, you can do this way:

#include <iostream>

typedef double (*func_t)(double);
struct func
{
  func_t fn;
  double (*calc)(func_t, double);
  double operator()(double x) {return calc(fn, x);}
};

double identity_calc(func_t fn, double x) {return fn(x);}

func identity(func_t fn)
{
  func f = {fn, identity_calc};
  return f;
}

double sqr(double x) { return x * x; }

int main() {
  func f = identity(sqr);
  std::cout << "sqr(100) = " << f(100) << std::endl;
}

But I don't think you will have much luck with plain C.

Guilherme Bernal
  • 8,183
  • 25
  • 43
1

defining a function inside a function in c ?

Is called Nested function.

Nested functions are not a part of ANSI C, however, they are part of Gnu C.

From wikipedia

Well known languages supporting lexically nested functions include:

ALGOL-based languages such as ALGOL 68, Simula, Pascal, Modula-2, Modula-3, Oberon, Seed7 and Ada.

Modern versions of Lisp (with lexical scope) such as Scheme, and Common Lisp.

ECMAScript (JavaScript, and ActionScript).

Scala (full support)

Various degrees of support in scripting languages such as Ruby, Python,Perl (starting with version 6).

Standard C and C++ do not support nested functions, but:GCC supports nested functions in C, as a language extension.

The D language, which is C-related, has nested functions.

Fortran, starting with Fortran-90, supports one level of nested (CONTAINed) subroutines and functions.

MATLAB (full support)

Example in GNU C syntax (C-extended with nested functions):

float E(float x)
{
    float F(float y)
    {
        return x + y;
    }
    return F(3) + F(4);
}
Gangadhar
  • 10,248
  • 3
  • 31
  • 50
1

Nested functions are not allowed in standard C

However they are available as a language extension in GCC

Since the question is tagged in C++. C++ also doesnt support nested functions. You may have a workaround like this:-

int main() 
{
  struct ABC {
    static void xyz()
    {
    }
  };

  ABC::xyz();

  return 0;
}

ie, you can have local classes.

Rahul Tripathi
  • 168,305
  • 31
  • 280
  • 331
1

comp.lang.c FAQ list · Question 20.24:

It's not trivial to implement nested functions such that they have the proper access to local variables in the containing function(s), so they were deliberately left out of C as a simplification. (gcc does allow them, as an extension.) For many potential uses of nested functions (e.g. qsort comparison functions), an adequate if slightly cumbersome solution is to use an adjacent function with static declaration, communicating if necessary via a few static variables. (A cleaner solution, though unsupported by qsort, is to pass around a pointer to a structure containing the necessary context.)

Community
  • 1
  • 1
haccks
  • 104,019
  • 25
  • 176
  • 264
-1

Usually you write your functions in an extra file/module. Make your inner function static and no one outside can use it.

mfg

Progga
  • 343
  • 1
  • 3
  • 11