折叠表达式 可以通过形参包的的实际参数(不是类型) 展开式子
这是这里说的几种 实际上并还有一些写法
先介绍这几种吧
#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()
我现所知晓的折叠表达式已经说完了