C++ 组合函数

C++中,组合类,类的析构函数调用顺序 // test4.cpp : 定义控制台应用程序的入口点。 //    1.声明一个CPU类,包含等级rank,频率frequency,电压voltage等属性,有两个共有函数 //    stop 和ran。 //    其中,rank为枚举类型CPU_Rank,声明为enum CPU_Rank{p1=1,p2,p3,p4,p5,p6,p7},frequency为单位 //    MHz整数,v... 阅读详情

组合函数是将N个一元函数组成一种更复杂的函数,每个函数的返回值作为参数传给下一个函数,直到传到最后一个函数结束。这种组合函数的能力可以使我们以一种更直观的方式去完成复杂的链式执行行为。例如有三个函数:

int f(int x), int g(int y), int h(int z)
依次调用三个函数
int a,b,c,parm; 
a = f(parm); 
b = g(a); 
c = h(b); 
等价于 c = h(g(f(parm)));

这种方式在使用起来不够简洁方便,如果能把这些简单函数组合起来,就可以按简单函数的方式去调用了,更加直观和简洁。比如像这样调用:

compose(f,g,h)(parm);

这种方式把这些函数串在一起了,内部是一个接一个调用并得到最终结果。

在c++中如何实现这种组合函数的调用呢?想想我们应该怎么做吧。我们先分析一下这种组合函数的调用的特点:

  • 都是一元函数;因为返回值要做下个函数的入参,返回值只有一个结果。
  • 一元函数的入参和返回值都是同一种类型;因为返回值要做下个函数的入参。
  • 按顺序从前往后调用。

通过上面的分析我们知道这种组合函数有个隐含的约束就是,返回值和入参必须相同,这也导致这些函数只能是一元函数。
如果希望有多个入参,则要通过变通的方式了,比如可以将一个结构体作为入参,类似于data_struct f(data_struct)来实现多个入参的问题。

好了现在看看c++中是如何实现这种调用的吧。

template <typename OuterFn, typename InnerFn>
class Composed
{
public:
	explicit Composed(OuterFn outerFn, InnerFn innerFn) :m_outerFn(outerFn), m_innerFn(innerFn) {}

public:
	template <typename Arg>
	auto operator()(Arg arg) -> decltype(declval<OuterFn>()((declval<InnerFn>()(declval<Arg>()))))
	{
		return m_outerFn(m_innerFn(arg));
	}

private:
	InnerFn m_innerFn;
	OuterFn m_outerFn;
};

template <typename Function1, typename Function2>
Composed<Function1, Function2> Compose(Function1 f1, Function2 f2)
{
	return Composed<Function1, Function2>(f1, f2);
}

template <typename Function1, typename Function2, typename Function3, typename... Functions>
auto Compose(Function1 f1, Function2 f2, Function3 f3, Functions... fs)->decltype(Compose(Compose(f1, f2), f3, fs...))
{
	return Compose(Compose(f1, f2), f3, fs...);
}

测试代码:

void TestCompose()
{
    auto f1 = [](int a){return a + 1; };
    auto g1 = [](int b){return b + 2; };
    auto h1 = [](int c){return c + 3; };
    auto I1 = [](int d){return d + 4; };
    auto J1 = [](int e){return e + 5; };

    auto ret = Compose(f1, g1, h1)(3);
    ret = Compose(f1, g1, h1, I1)(3);
    ret = Compose(f1, g1, h1, I1, J1)(3); 
    ret = Compose(f1, g1, h1, I1, J1, J1, J1)(3);
    ret = Compose([](int d){return d + 4; }, [](int d){return d + 5; })(3);

}

对于compose那里之前的代码在gcc下编译不过,原因是因为GCC和vs2013对于变参的展开规则不太一样导致的,GCC的展开规则更严格。

完整测试代码:

#include <vector>
#include <iostream>

using namespace std;
template <typename OuterFn, typename InnerFn>
class Composed
{
public:
	explicit Composed(OuterFn outerFn, InnerFn innerFn) :m_outerFn(outerFn), m_innerFn(innerFn) {}

public:
	template <typename Arg>
	auto operator()(Arg arg) -> decltype(declval<OuterFn>()((declval<InnerFn>()(declval<Arg>()))))
	{
		return m_outerFn(m_innerFn(arg));
	}

private:
	InnerFn m_innerFn;
	OuterFn m_outerFn;
};

template <typename Function1, typename Function2>
Composed<Function1, Function2> Compose(Function1 f1, Function2 f2)
{
	return Composed<Function1, Function2>(f1, f2);
}

template <typename Function1, typename Function2, typename Function3, typename... Functions>
auto Compose(Function1 f1, Function2 f2, Function3 f3, Functions... fs)->decltype(Compose(Compose(f1, f2), f3, fs...))
{
	return Compose(Compose(f1, f2), f3, fs...);
}
void TestCompose()
{
	auto f1 = [](int a){return a + 1; };
	auto g1 = [](int b){return b + 2; };
	auto h1 = [](int c){return c + 3; };
	auto I1 = [](int d){return d + 4; };
	auto J1 = [](int e){return e + 5; };

	auto ret = Compose(f1, g1, h1)(3);
	ret = Compose(f1, g1, h1, I1)(3);
	cout << ret << endl;
	ret = Compose(f1, g1, h1, I1, J1)(3);
	cout << ret << endl;
	ret = Compose(f1, g1, h1, I1, J1, J1, J1)(3);
	cout << ret << endl;
	ret = Compose([](int d){return d + 4; }, [](int d){return d + 5; })(3);
	cout << ret << endl;
}

int main()
{
	TestCompose();
	system("pause");
	return 0;
}



C++排列与组合算法详解 介绍一下排列组合算法 阅读详情

相关推荐

C++学习笔记:组合类的构造函数

C++学习笔记: 组合类的构造函数 关于学习组合类的构造函数和析构函数的一些体会: #include<iostream> #include<cmath> using namespace std; //测试组合类的使用 //Point class Point{ public: //普通构造函数 Point(int xx=0,int yy=0){ x=xx; y=yy; } //复制构造函数 Point(Point &p); //普

weixin_45514968的博客 1722

通用 排列/组合 函数(c++实现)

通用 排列/组合 函数 最近在编写小游戏的过程中发现,排列和组合会经常用到,而两个函数如果每次都编写的话,很容易出错。下面是我编写的通用的排列/组合函数 使用方法参考代码中的注释 #include #include using namespace std; #define SIZE_N 5 #define SIZE_K 0 /* combination 通用函数 使用方法: 1.

wangdeqiang2007的博客 1965

计算组合数的C++实现

组合数是组合数学中的一个重要概念,用于表示从一个给定集合中选择出若干个元素的不同方式的数量。在C++中,我们可以使用递归或动态规划的方法来计算组合数。动态规划是一种通过将问题分解为更小的子问题并保存子问题的解来解决复杂问题的方法。在计算组合数时,我们可以使用动态规划的思想,通过构建一个二维数组来保存中间结果。其中,C(n, k)表示从n个元素中选择k个元素的组合数。递归是一种自我调用的方法,用于将一个大问题分解为更小的子问题。通过两层循环,我们可以计算出所有的组合数,并返回最终结果。来保存中间结果,其中。

Meta_C的博客 733

[学习C++ ]C++ STL 全排列函数详解(排列组合与匹配算法)--1

一、概念   从n个不同元素中任取m(m≤n)个元素,按照一定的顺序排列起来,叫做从n个不同元素中取出m个元素的一个排列。当m=n时所有的排列情况叫全排列。如果这组数有n个,那么全排列数为n!个。   比如a,b,c的全排列一共有3!= 6 种 分别是{a, b, c}、{a, c, b}、{b, a, c}、{b, c, a}、{c, a, b}、{c, b, a}。 二、常用操作   ...

开源节流 2万+

C++编程:实现组合函数C(n, k)求解子集个数

动态规划(Dynamic Programming,DP)是一种在数学、管理科学、计算机科学、经济学和生物信息学等领域中用来解决某些类型的最优化问题的方法。其核心思想是将一个复杂问题分解为更小的子问题,通过解决这些子问题来解决原问题。在动态规划中,状态通常定义为数组或矩阵。对于组合数C(n, k),我们可以定义一个二维数组,其中dp[i][j]表示计算C(i, j)的值。状态转移方程为:当j = 0或j = i时,。

weixin_32836713的博客 1349

Pspice安装教程:Windows系统完整指南(含环境变量设置)

详细讲解在Windows系统中完成Pspice安装的全过程,涵盖安装步骤与关键的环境变量设置,帮助用户顺利运行仿真工具。适合初学者快速上手pspice安装教程中的核心环节。

weixin_42230607的博客 1179

高效学 C++|组合类的构造函数

设计好MyString类后,就可以像使用普通类型一样使用它了。例如,类的对象可以像普通的变量一样作为另一个类的数据成员。

不断学习,不断进步,提高自己 1134

POST 接口,将参数拼接到 URL 上,而不是将其作为表单数据发送

POST 接口,将参数拼接到 URL 上,而不是将其作为表单数据发送

pig_ning的博客 3146

C++中关于组合型仿函数的笔记

组合型仿函数 今天主要是对组合型仿函数进行了详细的总结,在C++的STL算法中,存在很多的算法通过对容器(vector、list、deque(顺序容器)、map、set(关联式容器))等的迭代器(iterator)进行一定的操作,可以达到效率和代码架构的一个整体优化。 但是在C++中存在很多的算法只能使用一元谓词或者二元谓词。在很多情况下,想通过某些算法对容器上的进行二元操作,但是在该算法只能使用一元谓词时,可以通过使用“一元组合函数配接器”和“二元函数配接器”。下面是实现的两种组合型仿函数的具体代码: #

weixin_44312010的博客 142

基于Q-learning的无人机三维路径规划(含完整C++代码)

基于Q-learning的无人机三维路径规划(含完整C++代码)

weixin_54186646的博客 1万+

logisim实验——通过2个半加器实现1-bit全加器,通过4个一位全加器构成4-bit加法器(详解)

一、由异或门和与门所构成的半加器: 二、由两个半加器构成的1-bit全加器: ..

zep 1万+

【C++ 函数式编程 】C++中的函数组合:用std::function实现编程艺术

C++中的函数组合:用std::function实现编程艺术

探索C++编程的奥秘,分享深入的技术见解和实践,旨在激发读者创造力与解决问题的思维。 2879

Stata新手避坑:用reghdfe搞定行业、地区多重固定效应,告别‘共线性’报错

本文详细介绍了如何使用Stata中的reghdfe命令高效处理多重固定效应问题,解决传统方法在面板回归中遇到的共线性报错和低R²问题。通过实战案例和高级技巧,帮助新手快速掌握行业、地区等多维固定效应的控制方法,提升经济学和金融学研究的分析效率。

weixin_30635053的博客 421

【C++】构造函数与类的组合以及初始化

构造函数 构造函数出现原因 举例桌子类Table,属性为长宽高,一个输出函数printf,一个设置函数set,在主函数内定义桌子类的对象t,输出该对象的属性,又定义了桌子属性类的对象t1,设置高为60,输出该对象的属性,如下代码所示:

qq_53830608的博客 2081

非技术面试题精选大全

回答提示:一般人回答这个问题过于平常,只说姓名、年龄、爱好、工作经验,这些在简历上都有,其实,企业最希望知道的是求职者能否胜任工作,包括:最强的技能、最深入研究的知识领域、个性中最积极的部分、做过的最成功的事,主要的成就等,这些都可以和学习无关,也可以和学习有关,但要突出积极的个性和做事的能力,说得合情合理企业才会相信。企业喜欢有礼貌的求职者。

吃面爱放香菜的博客 435

AI自瞄原理剖析(四)从Yolo推理坐标到屏幕坐标:基于FOV视角与焦距的坐标变换与精准瞄准

从Yolo推理框架得到的坐标到屏幕坐标的转换是一个涉及到FOV视角、焦距以及分辨率的复杂过程。通过数学公式,我们可以将推理框坐标反推为游戏内的实际坐标,并最终映射到屏幕坐标系中。利用这些信息,AI自瞄系统能够精确计算出准星从当前位置移动到敌人位置的距离,实现精准的自动瞄准。通过这种方法,AI自瞄系统能够在不同的游戏环境下灵活应对,提供高度精确的操作体验。在AI自瞄系统中,目标检测仅仅是第一步,获取到预测框的坐标后,我们还需要将这些坐标转换为实际屏幕上的精确位置。

代码简单说 Vue、JAVA、PHP、Node.js 熟练运用,接口、架构、性能全搞定。 1334

在C++11中实现函数式编程的组合子

本文介绍了在C++中实现常见函数式编程组合子的方法。通过C++11引入的lambda表达式和函数对象,实现了恒等组合子(返回输入函数)、组合组合子(函数串联)、应用组合子(函数应用)和Y组合子(递归实现)。文章详细说明了每种组合子的实现原理,并提供了具体的使用示例和验证测试。这些实现展示了如何在非函数式语言C++中应用函数式编程思想,但同时也指出需要注意性能开销问题。这些组合子工具为C++编程提供了新的思路,有助于编写更简洁、可读性更强的代码。

软件科学-郝学胜 919

QT-Creator安装教程(windows)

本文介绍了Qt的下载安装步骤:1)通过镜像源下载安装包;2)运行exe文件时使用命令行参数指定镜像地址;3)在安装过程中选择路径和自定义安装组件,包含QT5和QT6版本的详细安装说明;4)安装后可继续添加扩展包或卸载组件。重点提示了QT6必须勾选的关键组件,并提供了组件管理的操作方法。

qq_53545309的博客 3107

C++组合和继承 组合中会涉及到默认构造函数和拷贝构造函数的问题

背景    上午师弟让我看一下他遇到的问题,让我意识到组合问题理解的还不是很清晰,顺便把他的代码记录下来。        在speed类中需要使用wheel的一个对象,需要对wheel初始化,在speed的构造函数里使用了赋值初始化,所以在wheel中需要定义一个默认构造函数。第一眼看下边的代码觉得没问题,编译老是链接器错误在speed构造函数里,之后改为对象指针解决。后边慢慢看了一

老夫编代码就是一把梭 815

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

C++中组合类的构造函数相关问题

主要目的: 本代码主要目的在于探究在组合类中创建以及初始化对象时,各个类的构造函数的调用情况。 /*------------------------------------------------------------------------ 功能:探究组合类中构造函数的相关问题 运行结果: Calling the argument constructor of point... // 对应92...

田野麦子 1436

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

C++默认函数和类的组合07

C++默认函数和类的组合 完成优先于完美 直接上代码: 什么类的组合? <通过把别人的对象当做自己成员,然后访问“可访问”成员> 以另一个类的对象为数据成员 类的组合: 构造函数的写法,必须采用初始化参数列表的写法 #include"iostream" #include"string" using namespace std; class Boy{ public: Boy(string name, int age) :name(nam

PM2021的博客 208

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

CPP类的组合及拷贝构造函数

2019独角兽企业重金招聘Python工程师标准>>> ...

weixin_33752045的博客 215

理解C++存在继承和组合的对象构造函数调用顺序

理解C++存在继承和组合的对象构造函数调用顺序 例题 #include "bits/stdc++.h" // 虚函数能在析构函数里面调用吗 class C { public: C() { cout << "构造函数 C" << endl; } ~C() { cout << "析构函数 C" << endl; } }; cla...

【黑键】 491

C++面向对象之组合,继承与虚函数

最近部门主管要对我们这批实习生进行一次C++的考试。要考核组合,继承与虚函数的知识。所以自己就抽空一段代码,加深对组合与继承的理解。我对组合和继承的理解是: 一个类A由类B组成,或者说类A包含类B,前者就获得后者的接口,可以用后者的接口来实现自己的功能;而类A继承类B,类A可获得类B的接口,即类B的接口都属于类A所有。而组合关系类A只有使用类B接口的权限。 而虚函数是继承的范畴,组合没有虚函数...

qq_40319799的博客 208

组合数-c++函数解题思路

遇到组合数,第一件事就是想起它的求解公式,再想到阶乘,进而编写函数求解。

devil_nine的博客 4166

C++构造函数&析构函数&组合类

C++构造函数&析构函数 作用: C++在定义类的变量的时候,首先调用构造函数并且在类的变量被释放前调用析构函数。一般来讲,构造函数可以为类内成员变量来初始化,也可以对类内其他类的成员进行初始化。析构函数一般可以进行释放调用的资源。 构造函数: 在C++的类中,构造函数的名字与类的名字相同。构造函数的参数可以由这个类的变量来进行传递。构造函数还可以进行参数重载、参数默认 //class defination class stu{ public: stu(int a,int b); stu(

qq_33526880的博客 517
上一篇: 可变模板参数
下一篇: auto decltype 用于返回值类型后置时的占位
雪岢奇
博客等级 码龄17年 310粉丝 60原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值