当前位置: 首页 > article >正文

c++之说_13|模板 折叠表达式

折叠表达式 可以通过形参包的的实际参数(不是类型)  展开式子

这是这里说的几种  实际上并还有一些写法

先介绍这几种吧

#include <cstdio>
template<typename T,T... n>
struct integer_sequence
{
  T val;
};
template<int idx,typename _Tulp>
int get(_Tulp& t)
{
	
    return 0;
}
template<typename Ret,typename ...T>
using b = Ret(*)(T...);
b<void,int,int,int,int> _fun;

template<typename ...T>
void getc(T...)
{
}

template<typename T, T... ints>
auto call(integer_sequence<T, ints...> int_seq)
{
  T _tuple;
  
	//return getc((get<ints>(_tuple))...);
  //return getc(get<ints>(_tuple)...);
  //return ((get<ints>(_tuple),...));
  //return (ints||...);//一元右折叠
  //return (...,ints);//一元左折叠
 //return ((5*10)+...+ints);//二元左折叠
 //return (ints+...+(5*10));//二元右折叠
  
}
template<typename ...T>
auto call(T* ... c)//integer_sequence<T*, ints...> int_seq)
{
 	//return (c -> h,...);
  	//return (*_fun)(c -> h...);
    return (*_fun)(	[&](){return c->h;  }()...);
  // return (c&&...&&0);
}
template<typename T>
struct jk
{
  T h;
};

int main()
{
  	jk<int> b;
  	b.h = 10;
   call(&b,&b,&b,&b);
  call(integer_sequence<int, 0,1,2,3>());
}

return (ints||...);//一元右折叠
  //return (...,ints);//一元左折叠
 // return ((5*10)+...+ints);//二元左折叠
  //return (ints+...+(5*10));//二元右折叠

调用处 call(integer_sequence<int, 0,1,2,3>());

我们先看一元右折叠

return (ints||...);//一元右折叠

template<>
bool call<int, 0, 1, 2, 3>(integer_sequence<int, 0, 1, 2, 3> int_seq)
{
  int _tuple;
  return static_cast<bool>(0) || (static_cast<bool>(1) || (static_cast<bool>(2) || static_cast<bool>(3)));
}
//实例化后是如此

0|| 
(  1 || (  2 || 3 ) 

) 

是的外围没有小括号了

一元左折叠

 return (...,ints);//一元左折叠


template<>
int call<int, 0, 1, 2, 3>(integer_sequence<int, 0, 1, 2, 3> int_seq)
{
  int _tuple;
  return ((0 , 1) , 2) , 3;
}
这个清楚多了

二元左折叠

return ((5*10)+...+ints);//二元左折叠

template<>
int call<int, 0, 1, 2, 3>(integer_sequence<int, 0, 1, 2, 3> int_seq)
{
  int _tuple;
  return ((((5 * 10) + 0) + 1) + 2) + 3;
}

二元右折叠

return (ints+...+(5*10));//二元右折叠

template<>
int call<int, 0, 1, 2, 3>(integer_sequence<int, 0, 1, 2, 3> int_seq)
{
  int _tuple;
  return 0 + (1 + (2 + (3 + (5 * 10))));
}

好了简单的折叠式子给了

现在我们来看看有点不一样的

----------------------------------------------------

return getc( ( get<ints>(_tuple) )... );

比如这里  我们能看出想法

要根据 形参包实际的参数 ints 去调用并 铺开成为 

函数 getc 的参数

ints = {0,1};

return getc( (get<0>(_tuple)) , ( get<1>(_tuple)) );

实际上展开呢?

call(integer_sequence<int, 0,1,2,3>());//调用处


template<>
void call<int, 0, 1, 2, 3>(integer_sequence<int, 0, 1, 2, 3> int_seq)
{
  int _tuple;
  return getc((get<0>(_tuple)), (get<1>(_tuple)), (get<2>(_tuple)), (get<3>(_tuple)));
}

这个和我们之前看到的规则有些不同  什么一元二元 没用到哇

你说括号好多?不和我们平时调用的一样

return getc(get<ints>(_tuple)...);


template<>
void call<int, 0, 1, 2, 3>(integer_sequence<int, 0, 1, 2, 3> int_seq)
{
  int _tuple;
  return getc(get<0>(_tuple), get<1>(_tuple), get<2>(_tuple), get<3>(_tuple));
}

如此更改  括号没了

这个可以说就是 把  ... 左边的 成一个整体  get<ints>(_tuple)

有前提  必须得是在  类似于函数参数中

 return (get<ints>(_tuple)...);
这样写很遗憾是错误的
我们只能使用
一元二元的规则

 return (get<ints>(_tuple),...);


template<>
int call<int, 0, 1, 2, 3>(integer_sequence<int, 0, 1, 2, 3> int_seq)
{
  int _tuple;
  return get<0>(_tuple) , (get<1>(_tuple) , (get<2>(_tuple) , get<3>(_tuple)));
}


如果这样
return ((get<ints>(_tuple),...));

template<>
int call<int, 0, 1, 2, 3>(integer_sequence<int, 0, 1, 2, 3> int_seq)
{
  int _tuple;
  return (get<0>(_tuple) , (get<1>(_tuple) , (get<2>(_tuple) , get<3>(_tuple))));
}

外部就会多个括号

-------------------------------------------------------------------------------------------------------------

jk<int> b;
  	b.h = 10;
   call(&b,&b,&b,&b);
//调用处


template<typename ...T>
auto call(T* ... c)//integer_sequence<T*, ints...> int_seq)
{
 	return (c -> h,...);
  	//return (*_fun)(c -> h...);
   // return (*_fun)(	[&](){return c->h;  }()...);
  // return (c&&...&&0);
}

我们还可以访问类的成员

template<>
int call<jk<int>, jk<int>, jk<int>, jk<int> >(jk<int> * __c0, jk<int> * __c1, jk<int> * __c2, jk<int> * __c3)
{
  return __c0->h , (__c1->h , (__c2->h , __c3->h));
}

使用函数指针

template<typename Ret,typename ...T>
using b = Ret(*)(T...);

b<void,int,int,int,int> _fun;


return (*_fun)(c -> h...);


template<>
void call<jk<int>, jk<int>, jk<int>, jk<int> >(jk<int> * __c0, jk<int> * __c1, jk<int> * __c2, jk<int> * __c3)
{
  return (*_fun)(__c0->h, __c1->h, __c2->h, __c3->h);
}

lambda函数

 return (*_fun)(	[&](){return c->h;  }()...);
template<>
void call<jk<int>, jk<int>, jk<int>, jk<int> >(jk<int> * __c0, jk<int> * __c1, jk<int> * __c2, jk<int> * __c3)
{
      
  class __lambda_41_21
  {
    public: 
    inline /*constexpr */ int operator()() const
    {
      return __c0->h;
    }
    
    private: 
    jk<int> & * __c0;
    
    public:
    __lambda_41_21(jk<int> & * ___c0)
    : __c0{___c0}
    {}
    
  } __lambda_41_21{__c0};
  
    
  class __lambda_41_21
  {
    public: 
    inline /*constexpr */ int operator()() const
    {
      return __c1->h;
    }
    
    private: 
    jk<int> & * __c1;
    
    public:
    __lambda_41_21(jk<int> & * ___c1)
    : __c1{___c1}
    {}
    
  } __lambda_41_21{__c1};
  
    
  class __lambda_41_21
  {
    public: 
    inline /*constexpr */ int operator()() const
    {
      return __c2->h;
    }
    
    private: 
    jk<int> & * __c2;
    
    public:
    __lambda_41_21(jk<int> & * ___c2)
    : __c2{___c2}
    {}
    
  } __lambda_41_21{__c2};
  
    
  class __lambda_41_21
  {
    public: 
    inline /*constexpr */ int operator()() const
    {
      return __c3->h;
    }
    
    private: 
    jk<int> & * __c3;
    
    public:
    __lambda_41_21(jk<int> & * ___c3)
    : __c3{___c3}
    {}
    
  } __lambda_41_21{__c3};
  
 
return (*_fun)(__lambda_41_21.operator()(), __lambda_41_21.operator()(), __lambda_41_21.operator()(), __lambda_41_21.operator()());
 
大概就是这样
return (*_fun)(	[&](){return c->h;  }(),[&](){return c->h;  }(),[&](){return c->h;  }(),[&](){return c->h;  }());

从这里我们也可以看出 lambda 本质是是一个类里面

使用了 operator()

我现所知晓的折叠表达式已经说完了


http://www.kler.cn/a/232584.html

相关文章:

  • 408笔记合集
  • 【机器学习】如何配置anaconda环境(无脑版)
  • Linux系统编程多线程之条件变量和信号量讲解
  • HTTP 客户端怎么向 Spring Cloud Sleuth 传输跟踪 ID
  • JWT深度解析:Java Web中的安全传输与身份验证
  • Unity3D学习FPS游戏(12)敌人检测和攻击玩家
  • 贪心算法的应用
  • 【LangChain-04】利用权重和偏差跟踪和检查LangChain代理的提示
  • Pymysql之Connection中常用API
  • 20240206作业
  • 【人工智能】Fine-tuning 微调:解析深度学习中的利器(7)
  • 【Java】eclipse连接MySQL数据库使用笔记(自用)
  • Java面试题2024(Java面试八股文)
  • C语言---计算n的阶乘
  • 云计算运营模式介绍
  • <网络安全>《18 数据安全交换系统》
  • K8S系列文章之 [使用 Alpine 搭建 k3s]
  • 【Flink状态管理(二)各状态初始化入口】状态初始化流程详解与源码剖析
  • 开源大数据集群部署(十)Ranger usersync部署
  • 【RT-DETR有效改进】利用SENetV2重构化网络结构 (ILSVRC冠军得主,全网独家首发)
  • Springboot 整合 Elasticsearch(二):使用HTTP请求来操作ES
  • 开源大型语言模型概览:多语种支持与中文专注
  • ruoyi若依框架SpringSecurity实现分析
  • leetcode (算法)66.加一(python版)
  • 美国服务器如何
  • 眸思MouSi:“听见世界” — 用多模态大模型点亮盲人生活