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

本文详细介绍了C++中使用折叠表达式、模板、integer_sequence和lambda函数处理形参包的方法,展示了如何通过一元和二元折叠实现函数调用的展开,并探讨了lambda函数在这些场景中的应用。
摘要由CSDN通过智能技术生成

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

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

先介绍这几种吧

#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()

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

  • 10
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值