简体   繁体   English

C ++中的复合函数

[英]Composite function in C++

I am a beginner in C++ and want to do simple example of composite function. 我是C ++的初学者,想做一个简单的复合函数示例。 For example, in MATLAB, I can write 例如,在MATLAB中,我可以编写

a = @(x) 2*x
b = @(y) 3*y
a(b(1))

Answer is 6 答案是6

I searched following questions. 我搜索了以下问题。 function composition in C++ / C++11 and Function Composition in C++ C ++ / C ++ 11中的 函数组成和C ++中的函数组成

But they are created using advanced features, such as templates, to which I am not much familiar at this time. 但是它们是使用高级功能(例如模板)创建的,目前我对此还不太熟悉。 Is there a simple and more direct way to achieve this? 有没有简单而直接的方法来实现这一目标? In above MATLAB code, user does not need to know implementation of function handles. 在上面的MATLAB代码中,用户不需要知道函数句柄的实现。 User can just use proper syntax to get result. 用户可以使用正确的语法来获取结果。 Is there such way in C++? C ++中有这种方法吗?

** Another Edit:** **另一个编辑:**

In above code, I am putting a value at the end. 在上面的代码中,我将值放在最后。 However, if I want to pass the result to a third function, MATLAB can still consider it as a function. 但是,如果我要将结果传递给第三个函数,MATLAB仍可以将其视为一个函数。 But, how to do this in C++? 但是,如何在C ++中做到这一点?

For example, in addition to above code, consider this code: 例如,除了上面的代码,请考虑以下代码:

c = @(p,q) a(p)* b(q)  %This results a function
c(1,2)
answer=12

d = @(r) a(b(r))
d(1)
answer=6

function [ output1 ] = f1( arg1 )
val = 2.0;
output1 = feval(arg1,val)
end

f1(d)
answer = 12

In this code, c takes two functions as input and d is composite function. 在此代码中, c将两个函数用作输入,而d是复合函数。 In the next example, function f1 takes a function as argument and use MATLAB builtin function feval to evaluate the function at val . 在下一个示例中,函数f1接受一个函数作为参数,并使用MATLAB内置函数feval评估val处的函数。

How can I achieve this in C++? 如何在C ++中实现呢?

Perhaps I'm misunderstanding your question, but it sounds easy: 也许我误会了您的问题,但这听起来很简单:

int a(const int x) { return x * 2; }
int b(const int y) { return y * 3; }

std::cout << a(b(1)) << std::endl;

Regarding your latest edit, you can make a function return a result of another function: 关于您的最新编辑,您可以使一个函数返回另一个函数的结果:

int fun1(const int c) { return a(c); }

std::cout << fun1(1) << std::endl;

Note that this returns a number , the result of calling a , not the function a itself. 请注意,这返回一个数字 ,即调用a的结果,而不是函数a本身。 Sure, you can return a pointer to that function, but then the syntax would be different: you'd have to write something like fun1()(1) , which is rather ugly and complicated. 当然,您可以返回指向该函数的指针 ,但是语法会有所不同:您必须编写诸如fun1()(1) ,这相当丑陋且复杂。

How about: 怎么样:

#include <iostream>

int main(int, char**)
{
    auto a = [](int x) { return 2 * x; };
    auto b = [](int y) { return 3 * y; };

    for (int i = 0; i < 5; ++i)
        std::cout << i << " -> " << a(b(i)) << std::endl;

    return 0;
}

C++'s evaluation strategy for function arguments is always "eager" and usually "by value". C ++对函数参数的评估策略 始终是“渴望”, 通常是 “按值”。 The short version of what that means is, a composed function call sequence such as 这意味着它的简短版本是一个组合的函数调用序列,例如

x = a(b(c(1)));

is exactly the same as 与... 完全相同

{
  auto t0 = c(1);
  auto t1 = b(t0);
  x  = a(t1);
}

( auto t0 means "give t0 whatever type is most appropriate"; it is a relatively new feature and may not work in your C++ compiler. The curly braces indicate that the temporary variables t0 and t1 are destroyed after the assignment to x .) auto t0意思是“给t0任何最合适的类型”;这是一个相对较新的功能,在您的C ++编译器中可能不起作用。花括号表示将临时变量t0t1分配给x后会被销毁。)

I bring this up because you keep talking about functions "taking functions as input". 之所以提出这一点,是因为您一直在谈论函数“以函数作为输入”。 There are programming languages, such as R , where writing a(b(1)) would pass the expression b(1) to a , and only actually call b when a asked for the expression to be evaluated. 存在诸如编程语言, [R ,其中写a(b(1))将通过表达式 b(1)a ,并且仅实际调用 ba要求的表达进行评估。 I thought MATLAB was not like that, but I could be wrong. 以为 MATLAB不是那样的,但是我可能是错的。 Regardless, C++ is definitely not like that. 无论如何,C ++绝对不是那样。 In C++, a(b(1)) first evaluates b(1) and then passes the result of that evaluation to a ; 在C ++中, a(b(1))首先求值b(1) ,然后将求值结果传递给a a has no way of finding out that the result came from a call to b . a无法发现结果来自对b的调用。 The only case in C++ that is correctly described as "a function taking another function as input" would correspond to your example using feval . 在C ++中, 唯一被正确描述为“将另一个函数作为输入的函数”的情况将与使用feval的示例相对应。

Now: The most direct translation of the MATLAB code you've shown is 现在:您显示的MATLAB代码最直接的翻译是

#include <stdio.h>

static double a(double x)           { return 2*x; }
static double b(double y)           { return 3*y; }
static double c(double p, double q) { return a(p) * b(q); }
static double d(double r)           { return a(b(r)); }

static double f1(double (*arg1)(double))
{ return arg1(2.0); }

int main()
{
    printf("%g\n", a(b(1)));  // prints 6
    printf("%g\n", c(1,2));   // prints 12
    printf("%g\n", d(1));     // prints 6
    printf("%g\n", f1(d));    // prints 12
    printf("%g\n", f1(a));    // prints 4
    return 0;
}

(C++ has no need for explicit syntax like feval , because the typed parameter declaration, double (*arg1)(double) tells the compiler that arg1(2.0) is valid. In older code you may see (*arg1)(2.0) but that's not required, and I think it makes the code less readable.) (C ++不需要像feval这样的显式语法,因为类型化的参数声明double (*arg1)(double)告诉编译器arg1(2.0)是有效的。在较早的代码中,您可能会看到(*arg1)(2.0)但这不是必需的,我认为这会使代码的可读性降低。)

(I have used printf in this code, instead of C++'s iostreams, partly because I personally think printf is much more ergonomic than iostreams, and partly because that makes this program also a valid C program with the same semantics. That may be useful, for instance, if the reason you are learning C++ is because you want to write MATLAB extensions, which, the last time I checked, was actually easier if you stuck to plain C.) (我在此代码中使用了printf而不是C ++的iostream,部分原因是我个人认为printf比iostreams更符合人体工程学,部分原因是这使该程序成为具有相同语义的有效C程序。这可能对例如,如果您要学习C ++的原因是因为您想编写MATLAB扩展,那么我上次检查时,如果坚持使用普通C,实际上会更容易。)

There are significant differences; 有显着差异; for instance, the MATLAB functions accept vectors, whereas these C++ functions only take single values; 例如,MATLAB函数接受矢量,而这些C ++函数仅采用单个值; if I'd wanted b to call c I would have had to swap them or write a "forward declaration" of c above b ; 如果我想bc我将不得不交换他们或写的“前进宣言” c上述b ; and in C++, (with a few exceptions that you don't need to worry about right now,) all your code has to be inside one function or another. 在C ++中(除了一些您现在无需担心的例外),所有代码都必须位于一个或另一个函数中。 Learning these differences is part of learning C++, but you don't need to confuse yourself with templates and lambdas and classes and so on just yet. 学习这些差异是学习C ++的一部分,但是您无需将自己与模板,lambda和类等混淆。 Stick to free functions with fixed type signatures at first. 首先,请使用具有固定类型签名的免费功能。

Finally, I would be remiss if I didn't mention that in 最后,如果我不提及这一点,我将不知所措

static double c(double p, double q) { return a(p) * b(q); }

the calls to a and b might happen in either order . ab的调用可能以两种顺序发生。 There is talk of changing this but it has not happened yet. 有人说要改变它,但是还没有发生。

int a(const int x){return x * 2;}
int b(const int x){return x * 3;}
int fun1(const int x){return a(x);}

std::cout << fun1(1) << std::endl; //returns 2

This is basic compile-time composition. 这是基本的编译时组成。 If you wanted runtime composition, things get a tad more involved. 如果您想要运行时合成,那么事情会涉及更多。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM