2017-03-27 28 views
1

我最近在处理C代码时偶然发现了这个奇怪的想法。
我已经写的函数返回一个双和作为参数取在指针到功能和一定数量的参数,即是否可以编写一个函数,该函数返回一个指向与其参数中的函数不同的函数的指针?

double template_1(double (*)(double),...); 

此功能正确地识别真正的功能的特定属性

double f(double); 

表示为template_1中的指针,以使template_1对我可能插入的每个实际函数有效。

现在我不得不写另一个功能,让它成为:在参数˚F

double derivative(double (*)(double),double); 

double derivative(double (*f)(double),double x){ 

    double epsilon = ...; 

    return (f(x+epsilon)-f(x-epsilon))/(2.0*epsilon); 
} 

再次使其成为每˚F工作。 我的问题是:因为我想在template_1中使用derivative而不修改它,是否可以编写一个函数,该函数需要派生并吐出一些形式为double (*)(double)的东西?

我的想法是定义typedef double (*real_function)(double); 然后定义

real_function g(double (*derivative)(double (*)(double),double)) 

,我想它吐出来是这样的:double derivative_2(double x);所以我可以直接在template_1 argument 中定义类似g(derivative) = double (*h)(double);之类的东西,遗憾的是我并不知道如何完成这项工作,或者即使它可以工作。

+0

只有在已经定义了这个返回函数的情况下才有可能。不,你不能在运行时“定义”功能。你必须切换到一些函数式语言,例如Haskell或Lisp。 –

+0

在C运行时没有(便携)方式创建函数。 –

+0

@EugeneSh。大多数语言,而不仅仅是功能语言,支持这种(至少以某种形式) - 例如C++,java,go。 –

回答

1

警告:我是一个C++开发者很少ç知识,使随后的一切很可能unidiomatic C.

由于KerrekSB said,你将需要携带一些状态的功能。这对于原始函数来说是不可能的,但是您可以定义一个携带状态的结构体并添加一个可用于该结构体的函数。这显然有失去好的函数调用语法的缺点。我刮起一个例子:

#include <math.h> 
#include <stdio.h> 
#include <stdlib.h> 

typedef double (*raw_fptr)(double); 
struct real_function; 
typedef double (*evaluate_function)(struct real_function*, double); 

struct real_function { 
     evaluate_function evaluate; 
}; 
typedef struct real_function real_function; 

double evaluate(real_function *f, double x) { 
     if(f) { 
       return f->evaluate(f, x); 
     } 
     return NAN; 
} 

struct raw_real_function { 
     real_function real_function_base; 
     raw_fptr raw_function; 
}; 
typedef struct raw_real_function raw_real_function; 

double evaluate_raw_real_function(real_function *f_base, double x) { 
     if(f_base) { 
       raw_real_function *f = (raw_real_function*)f_base; 
       return f->raw_function(x); 
     } 
     return NAN; 
} 

raw_real_function make_raw_real_function(raw_fptr function) { 
     raw_real_function result; 
     result.raw_function = function; 
     result.real_function_base.evaluate = evaluate_raw_real_function; 
     return result; 
} 

struct derive_real_function { 
     real_function real_function_base; 
     real_function *function_to_derive; 
}; 
typedef struct derive_real_function derive_real_function; 

double derive(real_function *f_base, double x) { 
     derive_real_function *f = (derive_real_function*)f_base; 
     double epsilon = 1e-3; 
     double upper = evaluate(f->function_to_derive, x+epsilon); 
     double lower = evaluate(f->function_to_derive, x-epsilon); 
     double result = (upper - lower)/(2.0*epsilon); 
     return result; 
} 

derive_real_function make_derivative(real_function * function_to_derive) { 
     derive_real_function result; 
     result.real_function_base.evaluate = derive; 
     result.function_to_derive = function_to_derive; 
     return result; 
} 

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

int main(int argc, char **argv) { 
     raw_real_function x_cubed_wrapped = make_raw_real_function(x_cubed); 
     derive_real_function derived = make_derivative(&x_cubed_wrapped.real_function_base); 
     derive_real_function derived_twice = make_derivative(&derived.real_function_base); 
     double x = atof(argv[1]); 
     double derivative = evaluate(&derived.real_function_base, x); 
     double second_derivative = evaluate(&derived_twice.real_function_base, x); 
     printf("derivative of x^3 at %f = %f\n", x, derivative); 
     printf("second derivative of x^3 at %f = %f\n", x, second_derivative); 
     return 0; 
} 

见(轻微variaton,由于输入限制)运行here

它是如何工作的?我用结构体real_function,raw_real_functionderive_real_function伪造了一些继承来生成虚函数调用。 struct real_function充当仅由条目evaluate组成的虚拟功能表的容器。这个函数指针指向“导出”结构相关的评估功能:

raw_real_function实例指向evaluate_raw_real_function(如make_raw_real_function初始化derive_real_function实例指出evaluatederive(如make_derivative初始化)

当调用evaluate。在real_function_base成员上,它将调用相关的评估函数,该函数将real_function*转换为其关联的结构指针,并根据该信息执行所需的操作。

由于一切都只是real_function*,我们可以任意链接它们,但需要将“正常”功能转换为real_function格式,这就是make_raw_real_function所做的。

+0

我花了很长时间才明白答案,非常感谢。我想这里的主要教训是我会学习更多关于C++的知识 – Fra

2

在C中有一些方法可以做匿名函数。正如评论所说,它们不是可移植的。但根据使用情况,你可能会发现这个有用:Anonymous functions using GCC statement expressions

一对夫妇的人都似乎有类似的问题,不知道他们是如何携带,但他们可能会随机应变: https://github.com/graphitemaster/lambdapp https://github.com/Leushenko/C99-Lambda

基本上,如果有一种方法可以以不需要匿名函数的方式来构建程序,那么就这样做。如果你没有别的选择,那么我会给其中一个镜头。

+0

我会期待它谢谢你! – Fra

1

如果你有一个函数my_fancy_function

double my_fancy_function (double x) { return sin(x) + cos(x); } 

然后,您可以使用,为您创建的衍生功能的帮手宏。

#define DEFINE_DERIVATIVE_OF(FUNC) \ 
double derivative_of_ ## FUNC (double x) { \ 
    return derivative(FUNC, x); \ 
} 

DEFINE_DERIVATIVE_OF(my_fancy_function) 

然后,您将这个新定义的函数传递给您的模板。

template_1(derivative_of_my_fancy_function, x, y, z); 
+0

这是一个很棒的解决方案,但并不完全符合我的要求。 – Fra

相关问题